home *** CD-ROM | disk | FTP | other *** search
- // $Id: bytecode.cpp,v 1.12 1999/03/10 19:59:20 shields Exp $
- //
- // This software is subject to the terms of the IBM Jikes Compiler
- // License Agreement available at the following URL:
- // http://www.ibm.com/research/jikes.
- // Copyright (C) 1996, 1998, International Business Machines Corporation
- // and others. All Rights Reserved.
- // You must accept the terms of that agreement to use this software.
- //
-
- #include "assert.h"
- #include "config.h"
- #include "ast.h"
- #include "bytecode.h"
- #include "class.h"
- #include "control.h"
- #include "semantic.h"
- #include "stream.h"
- #include "symbol.h"
- #include "table.h"
- #include <iostream.h>
- #include <string.h>
- #ifndef __amigaos__
- #include <wchar.h>
- #endif
-
- #ifdef WIN32_FILE_SYSTEM
- #include <windows.h>
- #endif
-
-
-
- /*
- TODO:
- see if actually need call to ChangeStack, marked CHECK_THIS, in AssigmnentExpression
- */
-
-
- void ByteCode::CompileClass(TypeSymbol * type)
- {
- AstClassDeclaration * class_decl = type -> declaration -> ClassDeclarationCast();
- AstClassBody * class_body = (class_decl ? class_decl -> class_body :
- ((AstClassInstanceCreationExpression *) type -> declaration) -> class_body_opt);;
- int i;
- int mi,pi;
- AstConstructorDeclaration *constructor;
- AstMethodDeclaration *method;
- int super_init=0;
- u2 name;
- int descriptor;
- int need_init=0; // see if need to generate <init> method
- int need_clinit=0; // set if need <clinit> method
- Tuple<AstVariableDeclarator *> initialized_fields(type -> NumVariableSymbols()); // fields needing code to initialize
- int method_index;
- AstFieldDeclaration * field_decl;
- AstList * declarators;
- AstList * block_statements;
- int fi;
- int si;
- AstConstructorBlock * constructor_block;
- VariableSymbol * vsym;
- MethodSymbol * msym;
- AstStaticInitializer * static_initializer;
- class_literal_method = type -> outermost_type -> ClassLiteralMethod();
-
- //
- // Make sure there is an entry in the constant pool for all types on which
- // this type depends. This code is necessary because in the case of a dependence
- // on a type from which we only access a static final constant, the constant is
- // inlined and no other information about it is otherwise recorded.
- //
- for (TypeSymbol *parent = (TypeSymbol *) type -> parents -> FirstElement();
- parent;
- parent = (TypeSymbol *) type -> parents -> NextElement())
- {
- RegisterUtf8(parent -> signature);
- }
-
- //
- // Process static variables.
- //
- for (i=0; i < class_body -> NumClassVariables(); i++) {
- field_decl = class_body -> ClassVariable(i);
- for (int vi=0;vi<field_decl -> NumVariableDeclarators();vi++) {
- AstVariableDeclarator * vd = field_decl -> VariableDeclarator(vi);
- vsym = vd -> symbol;
- //
- // We need a static constructor-initializer if we encounter at least one class
- // variable that is declared with an initialization expression that is not a
- // constant expression.
- //
- need_clinit = need_clinit || (vd -> variable_initializer_opt && !(vsym -> ACC_FINAL() && vsym -> initial_value));
- DeclareField(vsym);
- }
- }
-
- // supply needed field declaration for this$0 (if there is one)
- for (pi = 0; pi < type -> NumConstructorParameters(); pi++)
- {
- DeclareField(type -> ConstructorParameter(pi));
- }
-
- //
- // supply needed field declaration for enclosing instances (this$n) if present
- //
- for (pi = 1; pi < type -> NumEnclosingInstances(); pi++)
- {
- DeclareField(type -> EnclosingInstance(pi));
- }
-
- // supply needed field declarations for "class " identifiers (used for X.class literals) if present
- for (int ri = 0; ri < type -> NumClassLiterals(); ri++)
- {
- DeclareField(type -> ClassLiteral(ri));
- }
-
- for (i=0; i < class_body -> NumInstanceVariables(); i++) {
- field_decl = class_body -> InstanceVariable(i);
- for (int vi=0;vi<field_decl -> NumVariableDeclarators();vi++) {
- AstVariableDeclarator * vd = field_decl -> VariableDeclarator(vi);
- DeclareField(vd -> symbol);
- // must set Constant attribute if initial value
- if (vd -> variable_initializer_opt) { // if initialization needed
- need_init=1;
- initialized_fields.Next() = vd;
- }
- }
- }
- // compile method bodies and constructors
- for (i=0; i < class_body -> NumMethods(); i++) {
- method = class_body -> Method(i);
- if (method -> method_symbol){
- method_index = BeginMethod(METHOD_KIND_ORDINARY, method -> method_symbol); // not constructor
- AstBlock *method_block = method -> method_body -> BlockCast();
- if (method_block) // not an abstract method ?
- (void) EmitStatement(method_block);
- EndMethod(METHOD_KIND_ORDINARY,method_index, method -> method_symbol); // not constructor
- }
- }
-
- //
- // NOTE that an abstract class that requires this patch may become out-of-date
- // and cause spurious messages to be emitted if any abstract method inherited
- // from an interface is later removed from that interface.
- //
- if (type -> ACC_ABSTRACT())
- {
- for (int i = 0; i < type -> expanded_method_table -> symbol_pool.Length(); i++)
- {
- MethodShadowSymbol *method_shadow_symbol = type -> expanded_method_table -> symbol_pool[i];
- MethodSymbol *method_symbol = method_shadow_symbol -> method_symbol;
- if (method_symbol -> ACC_ABSTRACT() &&
- method_symbol -> containing_type != type &&
- method_symbol -> containing_type -> ACC_INTERFACE())
- {
- if (! method_symbol -> IsTyped())
- method_symbol -> ProcessMethodSignature(&this_semantic, class_decl -> identifier_token);
- method_symbol -> ProcessMethodThrows(&this_semantic, class_decl -> identifier_token);
-
- method_index = BeginMethod(METHOD_KIND_ORDINARY, method_symbol);
- EndMethod(METHOD_KIND_ORDINARY,method_index, method_symbol);
- }
- }
- }
-
- // compile any private access methods
- for (i = 0; i < type -> NumPrivateAccessMethods(); i++) {
- MethodSymbol * method_sym = type -> PrivateAccessMethod(i);
- // AstMethodDeclaration * method_decl = method_sym -> method_or_constructor_declaration -> MethodDeclarationCast();
- method_index = BeginMethod(METHOD_KIND_ACCESS, method_sym);
- GenerateAccessMethod(method_sym);
- EndMethod(METHOD_KIND_ACCESS,method_index, method_sym);
- }
-
- if (type -> ClassLiteralMethod()) {
- MethodSymbol * class_literal_sym = type -> ClassLiteralMethod();
- // generate the class$ identity method used for class literal-related garbage mumbo-jumbo initialization
- method_index = BeginMethod(METHOD_KIND_ACCESS_CLASS, class_literal_sym);
- GenerateClassAccessMethod(class_literal_sym);
- EndMethod(METHOD_KIND_ACCESS_CLASS,method_index, class_literal_sym);
- }
-
- if (type -> block_initializer_method) {
- MethodSymbol * block_init_method = type -> block_initializer_method;
- method_index = BeginMethod(METHOD_KIND_ORDINARY, block_init_method);
- int fi=0, bi=0;
- while (fi < initialized_fields.Length() && bi < class_body -> NumBlocks()) {
- if (initialized_fields[fi] -> LeftToken() < class_body -> Block(bi) -> left_brace_token) {
- InitializeInstanceVariable(initialized_fields[fi++]);
- }
- else {
- (void) EmitStatement((AstStatement *) (class_body -> Block(bi++)));
- }
- }
-
- while (fi<initialized_fields.Length()) {
- InitializeInstanceVariable(initialized_fields[fi++]);
- }
-
- // compile any initialization blocks
-
- while (bi < class_body -> NumBlocks()) {
- (void) EmitStatement((AstStatement *) (class_body -> Block(bi++)));
- }
-
- PutOp(OP_RETURN);
- EndMethod(METHOD_KIND_ORDINARY,method_index,block_init_method); // is constructor
- }
-
- if (type -> NumGeneratedConstructors() == 0) {
- if (class_body -> default_constructor) {
- CompileConstructor(class_body -> default_constructor, initialized_fields);
- }
- else {
- for (i=0; i < class_body -> NumConstructors(); i++) {
- constructor = class_body -> Constructor(i);
- CompileConstructor(constructor, initialized_fields);
- }
- for (i = 0; i < type -> NumPrivateAccessConstructors(); i++) {
- MethodSymbol *constructor_sym = type -> PrivateAccessConstructor(i);
- AstConstructorDeclaration *constructor =
- constructor_sym -> method_or_constructor_declaration -> ConstructorDeclarationCast();
- CompileConstructor(constructor, initialized_fields);
- }
- }
- }
- else {
- for (i=0; i < type -> NumGeneratedConstructors(); i++) {
- MethodSymbol * this_constructor_symbol = type -> GeneratedConstructor(i);
- AstConstructorDeclaration * constructor =
- this_constructor_symbol -> method_or_constructor_declaration -> ConstructorDeclarationCast();
- constructor_block = constructor -> constructor_body -> ConstructorBlockCast();
- // compile generated constructor
- method_index = BeginMethod(METHOD_KIND_CONSTRUCTOR, this_constructor_symbol); // is constructor
- methods[method_index].name_index = RegisterUtf8(U8S_LT_init_GT_, strlen(U8S_LT_init_GT_));
-
- UpdateBlockInfo(this_constructor_symbol -> block_symbol);
-
- if (! constructor_block -> explicit_constructor_invocation_opt) {
- PutOp(OP_ALOAD_0);
- PutOp(OP_INVOKENONVIRTUAL); // no args, hence no need to call ChangeStack()
- PutU2(BuildMethodref(super_class,
- BuildNameAndType(RegisterUtf8(U8S_LT_init_GT_, strlen(U8S_LT_init_GT_)), RegisterUtf8(U8S_LP_RP_V, strlen(U8S_LP_RP_V)))));
- }
- else {
- (void) EmitStatement((AstStatement *) constructor_block -> explicit_constructor_invocation_opt);
- }
-
- for (si = 0;si < constructor_block -> NumLocalInitStatements();si++) {
- (void) EmitStatement((AstStatement *) constructor_block -> LocalInitStatement(si));
- }
-
- // supply needed field initialization unless constructor
- // starts with explicit 'this' call to another constructor
- if (! (constructor_block -> explicit_constructor_invocation_opt &&
- constructor_block -> explicit_constructor_invocation_opt -> ThisCallCast())) {
- if (type -> NumEnclosingInstances()) {
- VariableSymbol * this0_parameter = type -> EnclosingInstance(0);
- PutOp(OP_ALOAD_0); // load address of object on which method is to be invoked
- LoadLocal(1, this0_parameter -> Type());
- PutOp(OP_PUTFIELD);
- PutU2(GenerateFieldReference(this0_parameter));
- }
-
- if (class_body -> this_block) { // compile explicit 'this' call if present
- AstBlock * block = (AstBlock *) class_body -> this_block;
- for (si = 0;si < block -> NumStatements();si++) {
- (void) EmitStatement((AstStatement *) block -> Statement(si));
- }
- }
-
- if (! type -> block_initializer_method) {
- int fi=0,bi=0;
- while (fi < initialized_fields.Length() && bi < class_body -> NumBlocks()) {
- if (initialized_fields[fi] -> LeftToken() < class_body -> Block(bi) -> left_brace_token) {
- InitializeInstanceVariable(initialized_fields[fi++]);
- }
- else {
- AstBlock * block = (AstBlock *) (class_body -> Block(bi++));
- for (si = 0;si < block -> NumStatements();si++) {
- (void) EmitStatement((AstStatement *) block -> Statement(si));
- }
- }
- }
-
- while (fi<initialized_fields.Length()) {
- InitializeInstanceVariable(initialized_fields[fi++]);
- }
- // compile any initialization blocks
- while (bi < class_body -> NumBlocks()) {
- AstBlock * block = (AstBlock *) (class_body -> Block(bi++));
- for (si = 0;si < block -> NumStatements();si++) {
- (void) EmitStatement((AstStatement *) block -> Statement(si));
- }
- }
- }
- else {
- // generate a call to the parameterless function block_initializer_function
- PutOp(OP_ALOAD_0); // load address of object on which method is to be invoked
- PutOp(OP_INVOKENONVIRTUAL);
- CompleteCall(type -> block_initializer_method, 0, 0);
- }
- }
-
- (void) EmitStatement(constructor_block -> original_constructor_invocation);
- PutOp(OP_RETURN);
- EndMethod(METHOD_KIND_CONSTRUCTOR,method_index, this_constructor_symbol); // is constructor
-
- // compile method associated with generated constructor
- MethodSymbol * local_constructor_symbol = this_constructor_symbol -> LocalConstructor();
- method_index = BeginMethod(METHOD_KIND_CONSTRUCTOR, local_constructor_symbol); // is constructor
- methods[method_index].name_index =
- RegisterUtf8(local_constructor_symbol -> ExternalIdentity() -> Utf8_literal);
-
- for (si = 0;si < constructor_block -> block -> NumStatements();si++) {
- (void) EmitStatement((AstStatement *) constructor_block -> block -> Statement(si));
- }
- EndMethod(METHOD_KIND_CONSTRUCTOR,method_index,local_constructor_symbol); // is constructor
- }
- }
-
-
- if (class_body -> NumStaticInitializers() > 0 || need_clinit) {
- msym = type -> static_initializer_method;
- method_index = BeginMethod(METHOD_KIND_GENERATED_CONSTRUCTOR, msym);
- code_attribute -> max_locals = 0;
- // revisit members that are part of class initialization
- for (mi = 0; mi < class_body -> NumClassBodyDeclarations(); mi++) {
- static_initializer = class_body -> ClassBodyDeclaration(mi) -> StaticInitializerCast();
- if (static_initializer) {
- (void) EmitStatement((AstStatement *) static_initializer -> block);
- }
- else if (class_body -> ClassBodyDeclaration(mi) -> FieldDeclarationCast()) {
- field_decl = class_body -> ClassBodyDeclaration(mi) -> FieldDeclarationCast();
- // field declaration
- for (int vi=0;vi<field_decl -> NumVariableDeclarators();vi++) {
- AstVariableDeclarator * vd = field_decl -> VariableDeclarator(vi);;
- vsym = vd -> symbol;
- if (!vsym -> ACC_STATIC()) continue; // skip non-static fields
- InitializeClassVariable(vd);
- }
- }
- }
- PutOp(OP_RETURN);
- EndMethod(METHOD_KIND_GENERATED_CONSTRUCTOR,method_index,msym);
- }
- FinishCode(type);
-
- Write();
-
- #ifdef TEST
- if (this_control.option.debug_dump_class) PrintCode();
- #endif
- }
-
- //
- // initialized_fields is a list of fields needing code to initialize.
- //
- void ByteCode::CompileConstructor(AstConstructorDeclaration * constructor, Tuple<AstVariableDeclarator *> &initialized_fields)
- {
-
- MethodSymbol * method_symbol = constructor -> constructor_symbol;
- TypeSymbol * type = method_symbol -> containing_type;
- AstClassDeclaration * class_decl = type -> declaration -> ClassDeclarationCast();
- AstClassBody * class_body = (class_decl ? class_decl -> class_body :
- ((AstClassInstanceCreationExpression *) type -> declaration) -> class_body_opt);;
- AstBlock * block;
- int is_this=0; // set if start with this() call.
-
- int method_index;
- int fi;
- int si;
- int descriptor;
- AstConstructorBlock * constructor_block;
- AstList * block_statements;
-
- method_index = BeginMethod(METHOD_KIND_CONSTRUCTOR, method_symbol); // is constructor
- methods[method_index].name_index = RegisterUtf8(U8S_LT_init_GT_, strlen(U8S_LT_init_GT_));
-
- UpdateBlockInfo(method_symbol -> block_symbol);
-
- constructor_block = constructor -> constructor_body -> ConstructorBlockCast();
-
- if (! constructor_block -> explicit_constructor_invocation_opt) {
- if (super_class) {
- PutOp(OP_ALOAD_0);
- PutOp(OP_INVOKENONVIRTUAL); // no args, hence no need to call ChangeStack()
- PutU2(BuildMethodref(super_class,
- BuildNameAndType(RegisterUtf8(U8S_LT_init_GT_, strlen(U8S_LT_init_GT_)), RegisterUtf8(U8S_LP_RP_V, strlen(U8S_LP_RP_V)))));
- }
- }
- else {
- if (constructor_block -> explicit_constructor_invocation_opt -> ThisCallCast()) is_this=1;
- (void) EmitStatement((AstStatement *) constructor_block -> explicit_constructor_invocation_opt);
- }
-
- // supply needed field initialization unless constructor
- // starts with explicit 'this' call to another constructor
- if (!is_this) {
- if (type -> NumEnclosingInstances()) {
- VariableSymbol * this0_parameter = type -> EnclosingInstance(0);
- PutOp(OP_ALOAD_0); // load address of object on which method is to be invoked
- LoadLocal(1, this0_parameter -> Type());
- PutOp(OP_PUTFIELD);
- PutU2(GenerateFieldReference(this0_parameter));
- }
-
- if (class_body -> this_block) { // compile explicit 'this' call if present
- block = (AstBlock *) class_body -> this_block;
- for (si = 0;si < block -> NumStatements();si++) {
- (void) EmitStatement((AstStatement *)block -> Statement(si));
- }
- }
- if (!type -> block_initializer_method) {
- int fi=0,bi=0;
- while (fi < initialized_fields.Length() && bi < class_body -> NumBlocks()) {
- if (initialized_fields[fi] -> LeftToken() < class_body -> Block(bi) -> left_brace_token) {
- InitializeInstanceVariable(initialized_fields[fi++]);
- }
- else {
- AstBlock * block = (AstBlock *) (class_body -> Block(bi++));
- for (si = 0;si < block -> NumStatements();si++) {
- (void) EmitStatement((AstStatement *) block -> Statement(si));
- }
-
- }
- }
-
- while (fi<initialized_fields.Length()) {
- InitializeInstanceVariable(initialized_fields[fi++]);
- }
-
- // compile any initialization blocks
-
- while (bi < class_body -> NumBlocks()) {
- AstBlock * block = (AstBlock *) (class_body -> Block(bi++));
- for (si = 0;si < block -> NumStatements();si++) {
- (void) EmitStatement((AstStatement *) block -> Statement(si));
- }
- }
- }
- else {
- // generate a call to the parameterless function block_initializer_function
- PutOp(OP_ALOAD_0); // load address of object on which method is to be invoked
- PutOp(OP_INVOKENONVIRTUAL);
- CompleteCall(type -> block_initializer_method, 0, 0);
- }
-
- }
-
-
- (void) EmitStatement(constructor_block -> block);
-
- EndMethod(METHOD_KIND_CONSTRUCTOR,method_index, method_symbol);
- }
-
-
- void ByteCode::CompileInterface(TypeSymbol * type)
- {
- AstInterfaceDeclaration * interface_decl = type -> declaration -> InterfaceDeclarationCast();
- AstMethodDeclaration * method;
- int method_index;
- int i;
- int vi;
- int need_clinit=0; // set if need <clinit> method
- VariableSymbol * vsym;
- AstFieldDeclaration * field_decl;
- AstVariableDeclarator * vd;
- u2 name;
- AstList * declarators;
- for (i=0; i < interface_decl -> NumClassVariables(); i++) {
- field_decl = interface_decl -> ClassVariable(i);
-
- for (vi=0;vi<field_decl -> NumVariableDeclarators();vi++) {
- AstVariableDeclarator * vd = field_decl -> VariableDeclarator(vi);
- vsym = vd -> symbol;
- //
- // We need a static constructor-initializer if we encounter at least one class
- // variable that is declared with an initialization expression that is not a
- // constant expression.
- //
- need_clinit = need_clinit || (vd -> variable_initializer_opt && !(vsym -> ACC_FINAL() && vsym -> initial_value));
- DeclareField(vsym);
- }
- }
-
- for (i=0; i < interface_decl -> NumMethods(); i++) {
-
- method = interface_decl -> Method(i);
- if (method -> method_symbol){
- method_index = BeginMethod(METHOD_KIND_INTERFACE, method -> method_symbol); // not constructor
- EndMethod(METHOD_KIND_INTERFACE,method_index, method -> method_symbol);
- }
- }
-
- if (need_clinit) {
- method_index = BeginMethod(METHOD_KIND_GENERATED_CONSTRUCTOR, (MethodSymbol *) 0);
- code_attribute -> max_locals = 0;
- methods[method_index].SetACC_FINAL();
- // revisit members that are part of class initialization
- for (int mi = 0; mi < interface_decl -> NumClassVariables(); mi++) {
- // field declaration
- field_decl = interface_decl -> ClassVariable(mi);
- for (int vi2=0;vi2<field_decl -> NumVariableDeclarators();vi2++) {
- vd = field_decl -> VariableDeclarator(vi2);
- vsym = vd -> symbol;
- if (!vsym -> ACC_STATIC()) continue; // skip non-static fields
- InitializeClassVariable(vd);
- }
- }
- PutOp(OP_RETURN);
- EndMethod(METHOD_KIND_GENERATED_CONSTRUCTOR,method_index, (MethodSymbol *)0);
- }
- FinishCode(type);
-
- Write();
-
- #ifdef TEST
- if (this_control.option.debug_dump_class) PrintCode();
- #endif
-
- }
-
- void ByteCode::DeclareField(VariableSymbol * symbol)
- {
- int field_index = fields.NextIndex(); // index for field
-
- fields[field_index].access_flags = symbol -> access_flags;
- fields[field_index].name_index = RegisterUtf8(symbol -> ExternalIdentity() -> Utf8_literal);
- fields[field_index].descriptor_index = RegisterUtf8(symbol -> Type() -> signature);
-
- TypeSymbol *type = symbol -> Type();
- if (symbol -> ACC_FINAL() && symbol -> initial_value && (type -> Primitive() || type == this_control.String())) {
- u4 constant_value_attribute_length = 2;
- int lit_index = GetConstant(symbol -> initial_value, symbol -> Type());
-
- u2 name = RegisterUtf8(U8S_ConstantValue, strlen(U8S_ConstantValue));
- ConstantValue_attribute *constant_value_attribute = new ConstantValue_attribute(name, constant_value_attribute_length);
-
- constant_value_attribute -> constantvalue_index = lit_index;
- fields[field_index].attributes.Next() = constant_value_attribute;
- }
-
- if (symbol -> IsSynthetic())
- {
- fields[field_index].attributes.Next() = CreateSyntheticAttribute();
- }
-
- return;
- }
-
- void ByteCode::GenerateAccessMethod(MethodSymbol * method_symbol)
- {
- // generate code for access method to private member of containing class
-
- int stack_words = 0;
- int argument_offset = 0; // offset to start of argument
- code_attribute -> max_locals = 1; // DS fix this 01 dec 97
- TypeSymbol * parameter_type;
-
-
- VariableSymbol * field_sym = method_symbol -> accessed_member -> VariableCast();
- // generate code according to type of method
- if (method_symbol -> accessed_member -> MethodCast()) {
- // if accessing another method
- // copy arguments
- if (! method_symbol -> ACC_STATIC()) {
- PutOp(OP_ALOAD_0); // load address of object on which method is to be invoked
- }
- for (int i = 0; i < method_symbol -> NumFormalParameters(); i++) {
- TypeSymbol * local_type = method_symbol -> FormalParameter(i) -> Type();
- code_attribute -> max_locals += GetTypeWords(local_type);
- stack_words += GetTypeWords(local_type);
- LoadLocal(method_symbol -> ACC_STATIC() ? argument_offset: argument_offset+1, local_type);
- argument_offset += GetTypeWords(local_type); // update position in stack
- }
- PutOp(method_symbol -> ACC_STATIC() ? OP_INVOKESTATIC // must be static or private
- : OP_INVOKENONVIRTUAL);
- CompleteCall(method_symbol -> accessed_member -> MethodCast(), stack_words, 0);
- }
- else {
- // accessing field
- if (method_type == this_control.void_type) {
- // need method to assign value to field
- if (method_symbol -> NumFormalParameters()== 0) {
- chaos("assignment access method requires parameter");
- }
- parameter_type = method_symbol -> FormalParameter(0) -> Type();
- code_attribute -> max_locals += GetTypeWords(parameter_type);
-
- if (method_symbol -> ACC_STATIC()) {
- LoadLocal(0, parameter_type);
- PutOp(OP_PUTSTATIC);
- }
- else {
- PutOp(OP_ALOAD_0); // get this for field access
- LoadLocal(1, parameter_type);
- PutOp(OP_PUTFIELD);
- }
- ChangeStack(this_control.IsDoubleWordType(parameter_type) ? -2: -1);
- PutU2(GenerateFieldReference(method_symbol -> accessed_member -> VariableCast()));
- }
- else {
- // need method to retrieve value of field
- if (field_sym -> ACC_STATIC()) {
- PutOp(OP_GETSTATIC);
- ChangeStack(this_control.IsDoubleWordType(method_type) ? 2: 1);
- }
- else {
- PutOp(OP_ALOAD_0); // get this for field access
- PutOp(OP_GETFIELD);
- ChangeStack(this_control.IsDoubleWordType(method_type) ? 1: 0);
- }
- PutU2(GenerateFieldReference(field_sym));
- }
- }
-
- // method returns void, generate return unless last statement is return
- if (method_type == this_control.void_type) {
- // int line_index;
- // line_index = line_number_table_attribute -> line_number_table.NextIndex();
- // line_number_table_attribute -> line_number_table[line_index]
- PutOp(OP_RETURN);// guarantee return at end of body
- }
- else GenerateReturn(method_type);
- if (last_label_pc >= code_attribute -> code.Length()) {
- // here to emit noop if would otherwise EmitBranch past end
- PutNop(0);
- }
- }
-
- void ByteCode::GenerateReturn(TypeSymbol * type)
- {
- if (this_control.IsSimpleIntegerValueType(type)|| type==this_control.boolean_type) {
- PutOp(OP_IRETURN);
- }
- else if (type==this_control.long_type) {
- PutOp(OP_LRETURN);
- }
- else if (type==this_control.float_type) {
- PutOp(OP_FRETURN);
- }
- else if (type==this_control.double_type) {
- PutOp(OP_DRETURN);
- }
- else {// must be reference expression
- PutOp(OP_ARETURN);
- }
- }
-
- int ByteCode::BeginMethod(int method_kind, MethodSymbol * msym)
- {
- // is_constructor is set if this is constructor, is_generated_constructor is set is need to compile
- // default (no argument) constructor.
-
- BlockSymbol * block_symbol;
- TypeSymbol * throw_symbol;
- u4 length_code=0; // dummy value, will supply real value after code generated.
- int i;
- u4 line_number_table_attribute_length = 0;
- u4 exceptions_attribute_length = 0;
- u4 local_variable_table_attribute_length = 0;
- stack_depth = 0;
- last_label_pc = 0;
- last_op_pc = 0;
- last_op_nop = 0;
- this_block_depth = 0;
- int method_index = methods.NextIndex(); // index for method
- u2 name;
- switch (method_kind) {
- case METHOD_KIND_ORDINARY:
- case METHOD_KIND_ACCESS:
- case METHOD_KIND_ACCESS_CLASS:
- case METHOD_KIND_INTERFACE:
- methods[method_index].name_index = RegisterUtf8(msym -> ExternalIdentity() -> Utf8_literal);
- methods[method_index].descriptor_index = RegisterUtf8(msym -> signature);
- break;
- case METHOD_KIND_CONSTRUCTOR:
- // caller sets name
- methods[method_index].descriptor_index = RegisterUtf8(msym -> signature);
- break;
- case METHOD_KIND_GENERATED_CONSTRUCTOR:
- methods[method_index].name_index = RegisterUtf8(U8S_LT_clinit_GT_, strlen(U8S_LT_clinit_GT_));
- methods[method_index].descriptor_index = RegisterUtf8(U8S_LP_RP_V, strlen(U8S_LP_RP_V));
- methods[method_index].SetACC_STATIC();
- break;
- }
-
- if (method_kind==METHOD_KIND_CONSTRUCTOR || method_kind == METHOD_KIND_GENERATED_CONSTRUCTOR) {
- method_type = this_control.Object();
- if (msym == (MethodSymbol *) 0) {
- max_block_depth = 2;
- }
- else {
- max_block_depth = msym -> max_block_depth;
- }
- }
- else { // normal method declaration
- max_block_depth = msym -> max_block_depth;
- block_symbol = msym -> block_symbol;
- method_type = msym -> Type();
- }
- // set access flags for non-generated constructor. If we have
- // generated the constructore, then the access flags have been
- // set to be the same as those of the containing class.
- if (method_kind != METHOD_KIND_GENERATED_CONSTRUCTOR) {
- methods[method_index].access_flags = msym -> access_flags;
- }
- #ifdef MAKE_FINAL_PUBLIC
- if (method_kind==METHOD_KIND_ACCESS) { // DS debug 01 dec 97
- AccessFlags flags;
- flags.access_flags = methods[method_index].access_flags;
- flags.SetACC_PUBLIC();
- flags.SetACC_FINAL();
- methods[method_index].access_flags = flags.access_flags;
- }
- #endif
- if (msym)
- {
- if (msym -> IsSynthetic())
- {
- methods[method_index].attributes.Next() = CreateSyntheticAttribute();
- }
-
- //
- // Generate throws attribute if method throws any exceptions
- //
- if (msym -> NumThrows())
- {
- exceptions_attribute_length = 2 * (1 + msym -> NumThrows());
- name = RegisterUtf8(U8S_Exceptions, strlen(U8S_Exceptions));
- Exceptions_attribute * exceptions_attribute = new Exceptions_attribute(name, exceptions_attribute_length);
- for (int i = 0; i < msym -> NumThrows(); i++)
- {
- throw_symbol = (TypeSymbol *) msym -> Throws(i);
- exceptions_attribute -> exception_index_table.Next() = RegisterClass(throw_symbol -> fully_qualified_name);
- }
- methods[method_index].attributes.Next() = exceptions_attribute;
- }
- }
-
- if (method_kind==METHOD_KIND_INTERFACE) return method_index;
- // here if need code and associated attributes.
- if (this_control.option.g) {
- name = RegisterUtf8(U8S_LocalVariableTable, strlen(U8S_LocalVariableTable));
- local_variable_table_attribute= new LocalVariableTable_attribute(name, local_variable_table_attribute_length);
- }
- begin_labels = new Label[max_block_depth + 1];
- break_labels = new Label[max_block_depth + 1];
- continue_labels = new Label[max_block_depth + 1];
- test_labels = new Label[max_block_depth + 1];
- final_labels = new Label[max_block_depth + 1];
- monitor_labels = new Label[max_block_depth + 1];
- has_finally_clause = new int[max_block_depth+1];
- is_synchronized = new int[max_block_depth+1];
- block_symbols = new BlockSymbol *[max_block_depth+1];
- for (i=0;i<max_block_depth;i++) {
- has_finally_clause[i]=0; // reset has_finally_clause
- is_synchronized[i]=0; // reset has_finally_clause
- }
-
- if (! (msym && (msym -> ACC_ABSTRACT() || msym -> ACC_NATIVE())))
- {
- name = RegisterUtf8(U8S_Code, strlen(U8S_Code));
- code_attribute = new Code_attribute(name,length_code);
- code_attribute -> max_stack = 0;
- code_attribute -> max_locals = 0;
-
- if (method_kind==METHOD_KIND_CONSTRUCTOR || method_kind==METHOD_KIND_GENERATED_CONSTRUCTOR) {
- if (method_kind!=METHOD_KIND_GENERATED_CONSTRUCTOR) {
- block_symbol = msym -> block_symbol;
- if (block_symbol && block_symbol -> max_variable_index > code_attribute -> max_locals)
- {
- code_attribute -> max_locals = msym -> block_symbol -> max_variable_index;
- }
- }
- }
- else {
- block_symbol = msym -> block_symbol;
- if(block_symbol && block_symbol -> max_variable_index>code_attribute -> max_locals){
- code_attribute -> max_locals = block_symbol -> max_variable_index;
- }
- }
- code_attribute -> attribute_name_index = RegisterUtf8(U8S_Code, strlen(U8S_Code));
-
- line_number=0; // temporary until PC
- name = RegisterUtf8(U8S_LineNumberTable, strlen(U8S_LineNumberTable));
- line_number_table_attribute = new LineNumberTable_attribute(name, line_number_table_attribute_length);
- line_number_table_attribute -> attribute_name_index = name;
- }
-
- if (msym && msym -> NumFormalParameters()) {
- VariableSymbol * last_sym = (VariableSymbol *) msym -> FormalParameter(msym -> NumFormalParameters() - 1);
- last_parameter_index = last_sym -> LocalVariableIndex();
- }
- else {
- last_parameter_index = -1;
- }
- return method_index;
- }
-
- void ByteCode::EndMethod(int method_kind,int method_index, MethodSymbol *method_sym)
- {
- int i;
- u4 length_line_number_table_attribute = 0;
- this_block_depth=0;
- TypeSymbol * ptype;
- int has_code = 1; // Assume Code Attribute needed
- if (method_kind==METHOD_KIND_INTERFACE) return;
- if (method_kind==METHOD_KIND_CONSTRUCTOR || method_kind==METHOD_KIND_GENERATED_CONSTRUCTOR) {
- ptype= this_control.void_type;
- }
- else {
- ptype = method_sym -> Type();
- if (method_sym -> ACC_ABSTRACT() || method_sym -> ACC_NATIVE()) has_code = 0;
- }
- #ifdef NONO
- if (has_code && ptype==this_control.void_type) {
- // method returns void, generate return unless last statement is return
- // int line_index;
- // line_index = line_number_table_attribute -> line_number_table.NextIndex();
- // line_number_table_attribute -> line_number_table[line_index]
- PutOp(OP_RETURN);// guarantee return at end of body
- }
- #endif
- if (has_code) {
- if (last_label_pc >= code_attribute -> code.Length()) {
- // here to emit noop if would otherwise branch past end
- PutNop(0);
- }
-
- // attribute length:
- // need to review how to make attribute_name and attribute_length
- // only write line number attribute if -O not specified and there
- // are line numbers to write.
- if (!this_control.option.O && line_number_table_attribute -> line_number_table.Length()) {
- line_number_table_attribute -> attribute_length =
- line_number_table_attribute -> line_number_table.Length()*4 + 2;
- code_attribute -> attributes.Next() = line_number_table_attribute;
- }
- else { // line_number_table_attribute not needed, so delete it now
- delete line_number_table_attribute;
- }
- if (this_control.option.g) {
- if (method_kind==METHOD_KIND_ORDINARY) {
- if (! method_sym -> ACC_STATIC()) {
- // add 'this' to local variable table
- AddLocalVariableTableEntry(0, code_attribute -> code.Length(), RegisterUtf8(U8S_this, strlen(U8S_this)),
- RegisterUtf8(method_sym -> containing_type -> signature), 0);
- }
- }
- else if (method_kind==METHOD_KIND_CONSTRUCTOR && method_sym) {
- AddLocalVariableTableEntry(0, code_attribute -> code.Length(), RegisterUtf8(U8S_this, strlen(U8S_this)),
- RegisterUtf8(method_sym -> containing_type -> signature), 0);
- }
- if (method_kind==METHOD_KIND_ORDINARY || method_kind == METHOD_KIND_CONSTRUCTOR) {
- for (i = 0; i < method_sym -> NumFormalParameters(); i++) {
- VariableSymbol * parameter = method_sym -> FormalParameter(i);
- AddLocalVariableTableEntry(0, code_attribute -> code.Length(),
- RegisterUtf8(parameter -> ExternalIdentity() -> Utf8_literal),
- RegisterUtf8(parameter -> Type() -> signature),
- parameter -> LocalVariableIndex());
- }
- }
- if (local_variable_table_attribute -> local_variable_table.Length()) {
- local_variable_table_attribute -> attribute_length =
- local_variable_table_attribute -> local_variable_table.Length()*10 + 2;
- code_attribute -> attributes.Next() = local_variable_table_attribute;
- }
- }
- // std. fields of attribute_info
- int attribute_info_length = 0;
- for (i = 0; i < code_attribute -> attributes.Length(); i++) {
- if (code_attribute -> attributes[i] -> attribute_length) attribute_info_length += (code_attribute -> attributes[i] -> attribute_length+6);
- }
- code_attribute -> attribute_length = + 2 // for max_stack
- + 2 // for max_locals
- + 4 // for code_length
- + code_attribute -> code.Length() // for code
- + 2 // for exception_table_length
- + code_attribute -> exception_table.Length() * 8 // for exception table
- + 2 // for attributes_count
- + attribute_info_length
- ;
-
- methods[method_index].attributes.Next() = code_attribute;
- }
- delete [] begin_labels;
- delete [] break_labels;
- delete [] continue_labels;
- delete [] final_labels;
- delete [] monitor_labels;
- delete [] test_labels;
-
- delete [] has_finally_clause;
- delete [] is_synchronized;
- delete [] block_symbols;
-
- }
-
-
- void ByteCode::InitializeClassVariable(AstVariableDeclarator * vd)
- {
- VariableSymbol * symbol = vd -> symbol;
- AstExpression * expression;
- TypeSymbol * expression_type;
- if (vd -> variable_initializer_opt) { // field needs initialization
- expression = (AstExpression *) vd -> variable_initializer_opt;
- if (expression -> ArrayInitializerCast()) {
- InitializeArray(vd -> symbol ->Type(),
- expression -> ArrayInitializerCast());
- }
- else if (symbol -> ACC_FINAL() && expression -> IsConstant()) return; // if already initialized
- else if (!initialize_statics_in_clinit && expression -> IsConstant()) return; // if already initialized
- else {
- expression_type = expression -> Type();
- EmitExpression(expression);
- }
- PutOp(OP_PUTSTATIC);
- ChangeStack(this_control.IsDoubleWordType(expression_type) ? -2: -1);
- PutU2(GenerateFieldReference(symbol));
- }
- }
-
- void ByteCode::InitializeInstanceVariable(AstVariableDeclarator * vd)
- {
- VariableSymbol * symbol = vd -> symbol;
- TypeSymbol * type = symbol -> Type();
- AstExpression * expression;
- TypeSymbol * expression_type;
- if (vd -> variable_initializer_opt) { // field needs initialization
- expression = (AstExpression *) vd -> variable_initializer_opt;
- if (expression -> ArrayInitializerCast()) {
- PutOp(OP_ALOAD_0); // load 'this'
- InitializeArray(vd -> symbol ->Type(),
- expression -> ArrayInitializerCast());
- }
- else {
- expression_type = expression -> Type();
- PutOp(OP_ALOAD_0); // load 'this'
- EmitExpression(expression);
- }
- PutOp(OP_PUTFIELD);
- ChangeStack(this_control.IsDoubleWordType(expression_type) ? -2: -1);
- PutU2(GenerateFieldReference(symbol));
- }
- }
-
- void ByteCode::InitializeArray(TypeSymbol *type, AstArrayInitializer * array_initializer)
- {
- int i;
- AstExpression * expr;
- Ast * entry;
- TypeSymbol * subtype = type -> ArraySubtype();
- int num_ent = array_initializer -> NumVariableInitializers();
-
- LoadInteger(num_ent);
- EmitNewArray(1,type); // make the array
- for (i=0;i<num_ent;i++) {
- entry = array_initializer -> VariableInitializer(i);
- PutOp(OP_DUP);
- LoadInteger(i);
- expr=entry -> ExpressionCast();
- if (expr) {
- EmitExpression(expr);
- }
- else if (entry -> ArrayInitializerCast()) {
- InitializeArray(subtype, entry -> ArrayInitializerCast());
- }
- else chaos("wrong array initializer list element type");
-
- StoreArrayElement(subtype);
- }
- }
-
- void ByteCode::DeclareLocalVariable(AstVariableDeclarator * declarator)
- {
- AstArrayCreationExpression * ace;
- // generate code for local variable declaration.
- if (this_control.option.g) {
- declarator -> symbol -> local_program_counter = code_attribute -> code.Length();
- }
- if (declarator -> symbol -> initial_value) {
- (void) LoadLiteral(declarator -> symbol -> initial_value,declarator -> symbol -> Type()); // Is LiteralValue *
- }
- else if (declarator -> variable_initializer_opt) {
- ace = declarator -> variable_initializer_opt -> ArrayCreationExpressionCast();
- if (ace) {
- (void) EmitArrayCreationExpression(ace);
- }
- else if (declarator -> variable_initializer_opt -> ArrayInitializerCast()) {
- InitializeArray(declarator -> symbol ->Type(),
- declarator -> variable_initializer_opt -> ArrayInitializerCast());
- }
- else { // evaluation as expression
- EmitExpression(declarator -> variable_initializer_opt -> ExpressionCast());
- }
- }
- else return; // if nothing to initialize
-
- StoreLocalVariable(declarator -> symbol);
- }
-
- // JLS Chapter 13: Blocks and Statements
- // Statements control the sequence of evaluation of Java programs,
- // are executed for their effects and do not have values.
- //
- // Processing of loops requires a loop stack, especially to hangle
- // break and continue statements.
- // Loops have three labels, LABEL_BEGIN for start of loop body,
- // LABEL_BREAK to leave the loop, and LABEL_CONTINUE to continue the iteration.
- // Each loop requires a break label; other labels are defined and used
- // as needed.
- // Labels allocated but never used incur no extra cost in the generated
- // byte code, only in additional execution expense during compilation.
-
- int ByteCode::EmitStatement(AstStatement *statement)
- {
- // generate code for statement (JLS 13.4). The list of statement kinds
- // are those used in grammar, not precisely those used in JLS..
- // return 1 if execution of statement causes abrupt exit, 0 otherwise.
-
- LexStream::TokenIndex start;
- int abrupt = 0;
- if (statement -> kind !=Ast::BLOCK) {
- int line_number_index = line_number_table_attribute -> line_number_table.NextIndex();
- start = statement -> LeftToken();
- line_number_table_attribute -> line_number_table[line_number_index].line_number =
- this_semantic.lex_stream -> Line(start);
- line_number_table_attribute -> line_number_table[line_number_index].start_pc =
- code_attribute -> code.Length(); // pc at start of statement
- }
- stack_depth = 0; // stack empty at start of statement
-
- switch (statement -> kind) {
- case Ast::BLOCK: // JLS 13.2
- return EmitBlockStatement((AstBlock *) statement, 0);
-
- case Ast::LOCAL_VARIABLE_DECLARATION:// JLS 13.3
- {
- // generate code for local variable declaration.
- AstLocalVariableDeclarationStatement * lvds = statement -> LocalVariableDeclarationStatementCast();
- for (int i=0; i<lvds -> NumVariableDeclarators();i++) {
- DeclareLocalVariable(lvds -> VariableDeclarator(i));
- }
- }
- break;
- case Ast::EMPTY_STATEMENT: // JLS 13.5
- break;
- case Ast::EXPRESSION_STATEMENT: // JLS 13.7
- EmitStatementExpression(statement -> ExpressionStatementCast() -> expression);
- break;
- case Ast::IF: // JLS 13.8
- {
- AstIfStatement * ifStatement = (AstIfStatement *) statement;
- if (ifStatement -> expression -> IsConstant()) {
- IntLiteralValue *if_constant_expr = (IntLiteralValue *) ifStatement -> expression -> value;
- // Open question (DS, 20 Jan 97): Should be we setting abrupt here? If we weren't
- // doing this optimization, then we wouldn't be setting abrupt. Note that if expression
- // is, for example, non-zero and then-block terminates abruptly, then the following
- // statement is unreachable.
- if (if_constant_expr -> value)
- EmitStatement(ifStatement -> true_statement);
- else if (ifStatement -> false_statement_opt) // if there is false part
- EmitStatement(ifStatement -> false_statement_opt);
- }
- else {
- if (ifStatement -> false_statement_opt) { // if true and false parts
- Label label1;
- Label label2;
- int true_abrupt; // set if last statement in true block is abrupt exit
- int false_abrupt; // set if last statement in false block is abrupt exit
-
- EmitBranchIfExpression(ifStatement -> expression, false, label1);
- stack_depth = 0;
- true_abrupt = EmitStatement(ifStatement -> true_statement);
- if (!true_abrupt) {
- EmitBranch(OP_GOTO,label2);
- }
- DefineLabel(label1);
- false_abrupt = EmitStatement(ifStatement -> false_statement_opt);
- if (!true_abrupt) {
- DefineLabel(label2);
- }
- CompleteLabel(label1);
- CompleteLabel(label2);
- // if terminates abruptly only if both clauses terminate abruptly
- abrupt = true_abrupt ? false_abrupt : 0;
- }
- else { // if no false part
- Label label1;
- EmitBranchIfExpression(ifStatement -> expression, false, label1);
- stack_depth=0;
- (void) EmitStatement(ifStatement -> true_statement);
- DefineLabel(label1);
- CompleteLabel(label1);
- }
- }
- }
- break;
- case Ast::SWITCH: // JLS 13.9
-
- EmitSwitchStatement(statement -> SwitchStatementCast());
- break;
- case Ast::SWITCH_BLOCK: // JLS 13.9
- case Ast::CASE: // JLS 13.9
- case Ast::DEFAULT: // JLS 13.9
- // these nodes handled by SwitchStatement and
- // are not directly visited
- break;
- case Ast::WHILE:
- { // JLS 13.10
- AstWhileStatement * wp = statement -> WhileStatementCast();
- // branch to continuation test. This test is placed after the
- // body of the loop we can fall through into it after each
- // loop iteration without the need for an additional branch.
- int while_depth = this_block_depth;
- EmitBranch(OP_GOTO,continue_labels[while_depth]);
- DefineLabel(begin_labels[while_depth]);
- (void) EmitStatement(wp -> statement);
- DefineLabel(continue_labels[while_depth]);
- stack_depth=0;
- EmitBranchIfExpression(wp -> expression,true,
- begin_labels[while_depth]);
- CompleteLabel(begin_labels[while_depth]);
- CompleteLabel(continue_labels[while_depth]);
- }
- break;
- case Ast::DO: // JLS 13.11
- {
- AstDoStatement * sp = statement -> DoStatementCast();
- int do_depth=this_block_depth;
- DefineLabel(begin_labels[do_depth]);
- (void) EmitStatement(sp -> statement);
- DefineLabel(continue_labels[do_depth]);
- stack_depth=0;
- EmitBranchIfExpression(sp -> expression,true,
- begin_labels[do_depth]);
- CompleteLabel(begin_labels[do_depth]);
- CompleteLabel(continue_labels[do_depth]);
- }
-
- break;
- case Ast::FOR: // JLS 13.12
- {
- int i;
- int for_depth;
- AstForStatement * forStatement = statement -> ForStatementCast();
- for_depth=this_block_depth;
- for (i=0; i<forStatement -> NumForInitStatements();i++) {
- EmitStatement((AstStatement *) forStatement -> ForInitStatement(i));
- }
- EmitBranch(OP_GOTO,test_labels[for_depth]);
- DefineLabel(begin_labels[for_depth]);
- (void) EmitStatement(forStatement -> statement);
- DefineLabel(continue_labels[for_depth]);
- for (i=0; i<forStatement -> NumForUpdateStatements();i++) {
- (void) EmitStatement((AstStatement *) forStatement -> ForUpdateStatement(i));
- }
- DefineLabel(test_labels[for_depth]);
- if (forStatement -> end_expression_opt) {
- stack_depth=0;
- EmitBranchIfExpression(forStatement -> end_expression_opt,true,
- begin_labels[for_depth]);
- }
- else {
- EmitBranch(OP_GOTO,begin_labels[for_depth]);
- }
- CompleteLabel(begin_labels[for_depth]);
- CompleteLabel(test_labels[for_depth]);
- CompleteLabel(continue_labels[for_depth]);
- }
- break;
- case Ast::BREAK: // JLS 13.13
- ProcessAbruptExit(statement -> BreakStatementCast() -> nesting_level);
- EmitBranch(OP_GOTO,break_labels[statement -> BreakStatementCast() -> nesting_level]);
- abrupt = 1;
- break;
- case Ast::CONTINUE: // JLS 13.14
- ProcessAbruptExit(statement -> ContinueStatementCast() -> nesting_level);
- EmitBranch(OP_GOTO,continue_labels[statement -> ContinueStatementCast() -> nesting_level]);
- abrupt = 1;
- break;
- case Ast::RETURN: // JLS 13.15
- EmitReturnStatement(statement -> ReturnStatementCast());
- abrupt = 1;
- break;
- case Ast::SUPER_CALL:
- EmitSuperInvocation((AstSuperCall *) statement);
- break;
- case Ast::THIS_CALL:
- EmitThisInvocation((AstThisCall *) statement);
- break;
- case Ast::THROW: // JLS 13.16
- EmitExpression(statement -> ThrowStatementCast() -> expression);
- PutOp(OP_ATHROW);
- abrupt = 1;
- break;
- case Ast::SYNCHRONIZED_STATEMENT: // JLS 13.17
- EmitSynchronizedStatement(statement -> SynchronizedStatementCast());
- break;
- case Ast::TRY: // JLS 13.18
- EmitTryStatement(statement -> TryStatementCast());
- break;
- case Ast::CLASS: // Class Declaration
- case Ast::INTERFACE: // InterfaceDeclaration
- // these are factored out by the front end; and so must be skipped here
- break;
- case Ast::CATCH: // JLS 13.18
- case Ast::FINALLY: // JLS 13.18
- // handled by TryStatement
- default:
- chaos("unknown statement kind");
- break;
- }
- return abrupt;
- }
- void ByteCode::EmitReturnStatement(AstReturnStatement * statement)
- {
- int var_index=-1;
- int i;
- if (statement -> expression_opt == NULL) { // no return value
- ProcessAbruptExit(0);
- PutOp(OP_RETURN);
- return;
- }
- TypeSymbol * return_type = statement -> expression_opt-> Type();
-
- EmitExpression(statement -> expression_opt);
- if (method_type != return_type) {
- // no need to cast from reference to Object -- always ok
- if (method_type == this_control.Object() && IsReferenceType(return_type)) {
- }
- else {
- EmitCast(method_type, return_type);
- }
- }
- if (synchronized_blocks) {
- // if any outstanding synchronized blocks
- // find the index of the innermost enclosing block that is
- // synchronized. This block will have the variables allocated
- // for saving synchronization information.
- int synch_block=this_block_depth;
- for (i=this_block_depth;;i--) {
- if (is_synchronized[i]) {
- synch_block = i;
- break;
- }
- else if (i==0) {
- chaos("unable to find synchronization block");
- }
- }
-
- var_index=block_symbols[synch_block] -> synchronized_variable_index+2;;
-
- // if (this_control.IsDoubleWordType(return_type)) var_index--;
-
- }
- else if (finally_blocks) {
- for (i=this_block_depth;;i--) {
- if (has_finally_clause[i]) {
- var_index = has_finally_clause[i] - 1;
- var_index += 2; // move to start of area to save value
- break;
- }
- else if (i==0) {
- chaos("unable to find finally block");
- }
- }
- }
- if (var_index >= 0) { // if need to save before abrupt exit
- StoreLocal(var_index, method_type);
- ProcessAbruptExit(0);
- LoadLocal(var_index, method_type);
- }
- if (method_type != this_control.void_type) GenerateReturn(method_type);
- }
-
- int ByteCode::EmitBlockStatement(AstBlock *block, int synchronized)
- {
- BlockSymbol *block_symbol = block -> block_symbol;
- int nesting_level = block -> nesting_level;
-
- int length=0;
- int start_pc;
- int save_depth = this_block_depth;
- int this_depth = nesting_level;
- #ifdef TBSL
- AstStatement * last_statement;
- #endif
- int i;
- int last_kind=0;
-
- this_block_depth = nesting_level;
- is_synchronized[this_depth] = synchronized;
- synchronized_blocks += synchronized;
- block_symbols[this_depth] = block_symbol;
- start_pc = code_attribute -> code.Length();
- stack_depth = 0; // stack empty at start of statement
-
- if (this_depth>max_block_depth) {
- cout << "this_depth " << this_depth << "max " << max_block_depth << "\n";
- chaos("loops too deeply nested");
- }
-
- if (block -> NumStatements() > 0) {
- for (i=0; i<block -> NumStatements();i++){
- last_kind = EmitStatement((AstStatement *) block -> Statement(i));
- }
- if (this_block_depth != this_depth) {
- chaos("block depth out of synch!");
- }
- // this_block_depth = this_depth; // in case altered by one of above blocks
- }
-
- // if last statement is if_statement, must supply NOP to serve
- // as target for branch from true part
- // TODO - must refine this test so detect other cases where may
- // need following code, such as Switch, For, While; but
- // not if procedure returns void
- // code to end block (former end_block())
- // always define LABEL_BREAK at this point, and complete definition
- // of other labels
-
- if (IsLabelUsed(break_labels[this_depth])) {
- // need define only if used
- DefineLabel(break_labels[this_depth]);
- }
- CompleteLabel(begin_labels[this_depth]);
- CompleteLabel(break_labels[this_depth]);
- CompleteLabel(continue_labels[this_depth]);
- CompleteLabel(test_labels[this_depth]);
- CompleteLabel(begin_labels[this_depth]);
- if (is_synchronized[this_depth]) synchronized_blocks--;
- // if (this_block_depth) this_block_depth--;
- #ifdef TBSL
- if (block_statements) {
- if (block -> NumStatements()) {
- last_statement = (AstStatement *) block -> Statement(block -> NumStatements()-1);
- if (last_statement -> IfStatementCast()) {
- PutNop(1);
- }
- }
- }
- #endif
- // compute local variable table and max variable number
- UpdateBlockInfo(block_symbol);
- this_block_depth = save_depth;
- return last_kind;
- }
- void ByteCode::EmitStatementExpression(AstExpression * expression)
- {
- switch (expression -> kind) {
- case Ast::PARENTHESIZED_EXPRESSION:
- {
- AstParenthesizedExpression * pe =
- (AstParenthesizedExpression *) expression;
- EmitStatementExpression(pe -> expression);
- }
- break;
- case Ast::CALL:
- (void) EmitMethodInvocation((AstMethodInvocation *)expression, 0);
- if (expression-> Type()!=this_control.void_type) {
- if (this_control.IsDoubleWordType(expression-> Type())) {
- PutOp(OP_POP2);
- }
- else {
- PutOp(OP_POP); // discard value if used as statement
- }
- }
- break;
- case Ast::POST_UNARY:
- (void) EmitPostUnaryExpression((AstPostUnaryExpression *)expression,0);
- break;
- case Ast::PRE_UNARY:
- (void) EmitPreUnaryExpression((AstPreUnaryExpression *)expression,0);
- break;
- case Ast::ASSIGNMENT:
- EmitAssignmentExpression((AstAssignmentExpression *)expression,0);
- break;
- case Ast::CLASS_CREATION:
- (void) EmitClassInstanceCreationExpression((AstClassInstanceCreationExpression *) expression, 0);
- break;
- default:
- chaos("invalid statement expression kind");
- }
- }
- void ByteCode::EmitSwitchStatement(AstSwitchStatement * sws)
- {
- // generate code for switch statement. Good code generation requires
- // detailed knowledge of the target machine. Lacking this, we simply
- // choose between LOOKUPSWITCH and TABLESWITCH by picking that
- // opcode that takes the least number of bytes in the byte code.
- int use_lookup=0; // set if using LOOKUPSWITCH opcode
- // compare sizes os generated opcodes, ignoring size of common
- // header (opcode through default bytes).
- int high,low,ncases,switch_depth;
- int has_default;
- int op_start;
- int i;
- int nlabels;
- int map_index;
- int label_index;
- int start_pc;
- int ci;
- int di;
- AstBlock *switch_block=sws -> switch_block;
- BlockSymbol * block_symbol = switch_block -> block_symbol;
- switch_depth = sws -> switch_block -> nesting_level;
- EmitBlockStatement(switch_block, 0);
- // We need only worry about the presence of a default case if there
- // is code for it.
- start_pc = code_attribute -> code.Length();
- has_default = sws -> default_case.switch_block_statement!=NULL ? 1 : 0;
- ncases = sws -> map.Length();
- // Use tableswitch if have exact match or size of tableswitch
- // case is no more than 30 bytes more code than lookup case
- use_lookup=1;
- nlabels=ncases;
-
- if (ncases) {
- low = sws -> map[0] -> Value();
- high = sws -> map[ncases-1] -> Value();
- // want to compute
- // (2+high-low+1)<(1+ncases*2+30
- // but must guard against overflow, so factor out
- // high - low < ncases*2 + 28
- // but can't have number of labels < number of cases
- if ((high-low) < (ncases*2+28)) {
- use_lookup = 0; // use tableswitch
- nlabels = high-low + 1;
- }
- // correct estimate in case above computation gave ridiculous number
- // for the number of labels. (This is problem 096)
- if (nlabels < ncases) {
- use_lookup = 1;
- nlabels = ncases;
- }
- }
-
- EmitExpression(sws -> expression);
- stack_depth=0;
- PutOp(use_lookup ? OP_LOOKUPSWITCH : OP_TABLESWITCH);
- op_start = last_op_pc; // pc at start of instruction
- // supply any needed padding
- while(code_attribute -> code.Length() % 4) {
- PutNop(0);
- }
- // note that if no default clause in switch statement, must allocate
- // one that corresponds to do nothing and branches to start of next
- // statement.
- Label default_label;
- UseLabel(has_default ? default_label :
- break_labels[switch_depth],
- 4,code_attribute -> code.Length()-op_start);
-
- if (use_lookup) PutU4(ncases);
- else {
- PutU4(low);
- PutU4(high);
- }
- // how to allocate for proper length
- Label *case_labels = new Label[(use_lookup ? ncases : nlabels) + 1];
-
- if (use_lookup == 0) {
- int *has_tag = new int[nlabels + 1];
- for (i = 0; i < nlabels; i++) has_tag[i] = 0;
- // mark cases for which no case tag available, i.e., default cases
-
- for (i=0;i<sws -> switch_block -> NumStatements();i++) {
- int li;
-
- AstSwitchBlockStatement * sbs = (AstSwitchBlockStatement *)
- sws -> switch_block -> Statement(i);
- // process labels for this block
- for (li=0;li<sbs -> NumSwitchLabels();li++) {
- if (sbs -> SwitchLabel(li) -> CaseLabelCast()) {
- map_index =sbs -> SwitchLabel(li) -> CaseLabelCast() -> map_index;
- di =sws -> map[map_index] -> index;
- // label_index = sws -> map[di] -> Value() - low;
- label_index = sws -> map[map_index] -> Value() - low;
- has_tag[label_index]=1;
-
- }
- }
- }
- // now emit labels in instruction, using appropriate index
- for (i=0;i<nlabels;i++) {
- UseLabel(has_tag[i] ? case_labels[i] :
- has_default ? default_label
- : break_labels[switch_depth],
- 4,code_attribute -> code.Length()-op_start);
- }
-
- delete [] has_tag;
- }
- else {
- for (i=0;i<ncases;i++) {
- PutU4(sws -> map[i] -> Value());
- UseLabel(case_labels[sws -> map[i] -> index],4,code_attribute -> code.Length()-op_start);
- }
- }
- // march through switch block statements, compiling blocks in
- // proper order. We must respect order in which blocks seen
- // so that blocks lacking a terminal break fall through to the
- // proper place.
- for (i=0;i<sws -> switch_block -> NumStatements();i++) {
- int li;
-
- AstSwitchBlockStatement * sbs = (AstSwitchBlockStatement *)
- sws -> switch_block -> Statement(i);
- // process labels for this block
- for (li=0;li<sbs -> NumSwitchLabels();li++) {
- if (sbs -> SwitchLabel(li) -> CaseLabelCast()) {
- map_index =sbs -> SwitchLabel(li) -> CaseLabelCast() -> map_index;
- if (use_lookup) {
- DefineLabel(case_labels[map_index]);
- }
- else {
- int found=0;
- // look for case with same index and
- // use its value to find label index.
- for (int di2=0;di2<sws -> map.Length();di2++) {
- if (sws -> map[di2] -> index==map_index) {
- ci = sws -> map[di2] -> Value()-low;
- DefineLabel(case_labels[ci]);
- found=1;
- break;
- }
- }
- if (found==0)
- chaos("unable to find case label");
- }
- }
- else {
- if (sbs -> SwitchLabel(li) -> DefaultLabelCast()) {
- if (has_default) {
- DefineLabel(default_label);
- }
- else {
- chaos("error in processing default label");
- }
- }
- }
- }
- // compile code for this case
- for (li=0;li<sbs -> NumStatements();li++) {
- (void) EmitStatement(sbs -> Statement(li) -> StatementCast());
- }
- }
- UpdateBlockInfo(block_symbol);
- for (i=0;i<nlabels;i++) {
- if (case_labels[i].uses.Length() && case_labels[i].defined==0) {
- case_labels[i].defined=1;
- if (has_default) {
- case_labels[i].definition=default_label.definition;
- }
- else {
- case_labels[i].definition = break_labels[switch_depth].definition;
- }
- }
- CompleteLabel(case_labels[i]);
- }
-
- if (has_default) {
- CompleteLabel(default_label);
- }
- // define target of break label
- if (IsLabelUsed(break_labels[switch_depth])) { // need define only if used
- DefineLabel(break_labels[switch_depth]);
- }
- for (i=0;i<nlabels;i++) {
- if (case_labels[i].uses.Length() && case_labels[i].defined==0) {
- case_labels[i].defined=1;
- if (has_default) {
- case_labels[i].definition=default_label.definition;
- }
- else {
- case_labels[i].definition = break_labels[switch_depth].definition;
- }
- }
- CompleteLabel(case_labels[i]);
- }
-
- if (has_default) {
- CompleteLabel(default_label);
- }
- // define target of break label
- if (IsLabelUsed(break_labels[switch_depth])) { // need define only if used
- CompleteLabel(break_labels[switch_depth]);
- }
-
-
- // note that if using table, then must provide slot for every
- // entry in the range low..high, even though the user may not
- // have provided an explicit entry, in which case the default
- // action is to be taken. For example
- // switch (e) {
- // case 1:2:3: act1; break;
- // case 5:6: act2; break;
- // default: defact; break;
- // }
- // translated as
- // switch (e)
- // switch (e) {
- // case 1:2:3: act1; break;
- // case 4: goto defa:
- // case 5:6: act2; break;
- // defa:
- // default: defact;
- // }
-
- delete [] case_labels;
- }
-
-
-
- // 13.18 The try statement
- void ByteCode::EmitTryStatement(AstTryStatement * statement)
- {
- AstFinallyClause * finally_clause;
- int start_pc,end_pc;
- int exception_index,handler_pc;
- Label end_label;
- AstCatchClause * catch_clause;
- int last_abrupt=0; // set if last statement in try block is abrupt exit
- int try_depth = statement -> block -> nesting_level - 1;;
- int final_depth = try_depth + 1;
- BlockSymbol * block_symbol;
- start_pc = code_attribute -> code.Length(); // start pc
- if (statement -> finally_clause_opt) {
- // call finally block if have finally handler
- assert(block_symbols[try_depth]);
- block_symbol = block_symbols[try_depth] -> BlockCast();
- finally_clause = statement -> finally_clause_opt;
- has_finally_clause[final_depth]=1 + block_symbol -> try_variable_index;
- finally_blocks++;
- }
- last_abrupt = EmitStatement(statement -> block);
- // increment max_stack in case exception thrown while stack at greatest depth
- code_attribute -> max_stack++;
- if (statement -> finally_clause_opt) { // call finally block if have finally handler
- PutOp(OP_JSR);
- UseLabel(final_labels[final_depth], 2, 1);
- }
-
- if (!last_abrupt) {
- EmitBranch(OP_GOTO,end_label);
- }
- PutNop(0); // emit NOP so end_pc will come out right
- end_pc = last_op_pc;
- // process catch clauses
- int catch_abrupt=0;
- for (int i = 0; i<statement -> NumCatchClauses();i++) {
- catch_clause = statement -> CatchClause(i);
- VariableSymbol * parameter_symbol = catch_clause -> parameter_symbol;
- handler_pc = code_attribute -> code.Length();
- StoreLocalVariable(parameter_symbol);
- catch_abrupt = EmitStatement(catch_clause -> block);
-
- exception_index = code_attribute -> exception_table.NextIndex();
- code_attribute -> exception_table[exception_index].start_pc = start_pc;
- // add 1 to end_pc since it is exclusive, while start_pc
- // is inclusive. See footnote in 4.4.4 of JVM Specification
- //code_attribute -> exception_table[exception_index].end_pc = end_pc + 1; // DS 11 feb
- code_attribute -> exception_table[exception_index].end_pc = end_pc; // DS 11 feb
- code_attribute -> exception_table[exception_index].handler_pc = handler_pc;
- code_attribute -> exception_table[exception_index].catch_type =
- RegisterClass(parameter_symbol-> Type() -> fully_qualified_name);
- if (statement -> finally_clause_opt) { // call finally block if have finally handler
- PutOp(OP_JSR);
- UseLabel(final_labels[final_depth], 2, 1);
- }
- if (! catch_abrupt) {
- EmitBranch(OP_GOTO,end_label);
- }
- }
-
-
- if (statement -> finally_clause_opt) {
- handler_pc = code_attribute -> code.Length();
- has_finally_clause[final_depth] = 0; // reset once finally clause processed
- finally_blocks--;
-
- // handler for finally()
-
- // push thrown value
- StoreLocal(block_symbol -> try_variable_index, this_control.Object());
- PutOp(OP_JSR);
- UseLabel(final_labels[final_depth], 2, 1);
- LoadLocal(block_symbol -> try_variable_index, this_control.Object());
- PutOp(OP_ATHROW); // and rethrow the value to the invoker
-
- DefineLabel(final_labels[final_depth]);
- CompleteLabel(final_labels[final_depth]);
- StoreLocal(block_symbol -> try_variable_index+1, this_control.Object()); // save return address
- (void) EmitStatement(statement -> finally_clause_opt -> block);
- PutOp(OP_RET);
- PutU1(block_symbol -> try_variable_index + 1); // return using saved address
- exception_index = code_attribute -> exception_table.NextIndex();
- code_attribute -> exception_table[exception_index].start_pc = start_pc;
- code_attribute -> exception_table[exception_index].end_pc = handler_pc;
- code_attribute -> exception_table[exception_index].handler_pc = handler_pc;
- code_attribute -> exception_table[exception_index].catch_type = 0;
- }
-
- if (IsLabelUsed(end_label)) {
- DefineLabel(end_label);
- CompleteLabel(end_label);
- PutNop(1); // to make sure have code after end of try statement
- }
- else {
- CompleteLabel(end_label);
- }
- }
-
- void ByteCode::UpdateBlockInfo(BlockSymbol * block_symbol)
- {
- int i;
-
- if (code_attribute -> max_locals<block_symbol -> max_variable_index) {
- code_attribute -> max_locals = block_symbol -> max_variable_index;
- }
- if (block_symbol == (BlockSymbol *) 0) {
- chaos("null block symbol");
- }
-
-
- if (this_control.option.g) {
- // compute local variable table
- for (i = 0; i < block_symbol -> NumVariableSymbols();i++) {
- VariableSymbol * sym = block_symbol -> VariableSym(i);
- // only make entry if defined within range
- if (last_op_pc > sym -> local_program_counter) {
- AddLocalVariableTableEntry(sym -> local_program_counter,
- last_op_pc - sym -> local_program_counter,
- RegisterUtf8(sym -> ExternalIdentity() -> Utf8_literal),
- RegisterUtf8(sym-> Type() -> signature),
- sym -> LocalVariableIndex());
- }
- }
- }
- }
-
- void ByteCode::ProcessAbruptExit(int to_lev)
- {
- // exit to block at level lev, freeing monitor locks and invoking finally clauses as appropriate
- for (int lev=this_block_depth;lev>to_lev;lev--) {
- if (has_finally_clause[lev]) {
- PutOp(OP_JSR);
- UseLabel(final_labels[lev], 2, 1);
- }
- else if (is_synchronized[lev]) {
- PutOp(OP_JSR);
- UseLabel(monitor_labels[lev], 2, 1);
- }
- }
-
- }
-
- void ByteCode::EmitBranch(unsigned int opc, Label& lab) {
- // generate branch
- PutOp(opc);
- UseLabel(lab,2,1);
- }
-
-
- void ByteCode::EmitBranchIfExpression(AstExpression *p, bool cond,Label &lab)
- {
- // java provides a variety of conditional branch instructions, so
- // that a number of operators merit special handling:
- // constant operand
- // negation (we eliminate it)
- // equality
- // && and || (partial evaluation)
- // comparisons
- // Other expressions are just evaluated and the appropriate
- // branch emitted.
- AstExpression *left,*right,*temp;
- AstPreUnaryExpression *pre;
- TypeSymbol *left_type, *right_type;
-
- if (p -> ParenthesizedExpressionCast()) {
- p = UnParenthesize(p);
- }
- if (p -> IsConstant()) {
- if (IsZero(p)) {
- if (cond == false) EmitBranch(OP_GOTO,lab);
- }
- else {
- if (cond == true) EmitBranch(OP_GOTO,lab);
- }
- return;
- }
- pre = p -> PreUnaryExpressionCast();
- if (pre) { // must be !, though should probably
-
- // branch_if(!e,c,l) => branch_if(e,!c,l)
- // test opcode
- // call again with complementary control expression to show
- // effect of negation
- if (pre -> pre_unary_tag == AstPreUnaryExpression::NOT) {
- EmitBranchIfExpression(pre -> expression,cond == true ? false : true, lab);
- return;
- }
- else {
- chaos("branch_if expects ! in this context");
- }
- }
- // dispose of non-binary expression case by just evaluating
- // operand and emitting appropiate test.
- if (!(p -> BinaryExpressionCast())) {
- EmitExpression(p);
- EmitBranch(cond == true ? OP_IFNE : OP_IFEQ,lab);
- return;
- }
- // Here if binary expression, so extract operands
- AstBinaryExpression * bp = (AstBinaryExpression *) p;
- left = bp -> left_expression;
- if (left -> ParenthesizedExpressionCast()) {
- left = UnParenthesize(left);
- }
- right = bp -> right_expression;
- if (right -> ParenthesizedExpressionCast()) {
- right = UnParenthesize(right);
- }
- left_type = left-> Type();
- right_type = right-> Type();
- switch (bp -> binary_tag) {
- case AstBinaryExpression::INSTANCEOF:
- {
- EmitExpression(left);
- PutOp(OP_INSTANCEOF);
- TypeSymbol * instanceof_type = bp -> right_expression-> Type();
- if (instanceof_type -> num_dimensions) {
- PutU2(RegisterClass(instanceof_type -> signature));
- }
- else {
- PutU2(RegisterClass(instanceof_type -> fully_qualified_name));
- }
- EmitBranch(cond == true? OP_IFNE : OP_IFEQ,lab);
- }
- return;
- case AstBinaryExpression::AND_AND:
- /*
- branch_if(a&&b, true, lab) =>
- branch_if(a,false,skip);
- branch_if(b,true,lab);
- skip:
- branch_if(a&&b, false, lab) =>
- branch_if(a,false,lab);
- branch_if(b,false,lab);
- */
- if (cond == true) {
- Label skip;
- EmitBranchIfExpression(left, false, skip);
- EmitBranchIfExpression(right, true, lab);
- DefineLabel(skip);
- CompleteLabel(skip);
- }
- else {
- EmitBranchIfExpression(left, false, lab);
- EmitBranchIfExpression(right, false, lab);
- }
- return;
- case AstBinaryExpression::OR_OR:
- /*
- branch_if(a||b,true,lab) =>
- branch_if(a,true,lab);
- branch_if(b,true,lab);
- branch_if(a||b,false,lab) =>
- branch_if(a,true,skip);
- branch_if(b,false,lab);
- There is additional possibility of one of the operands being
- constant that should be dealt with at some point.
- */
- if (cond == true) {
- EmitBranchIfExpression(left, true, lab);
- EmitBranchIfExpression(right, true, lab);
- }
- else {
- Label skip;
- EmitBranchIfExpression(left, true, skip);
- EmitBranchIfExpression(right, false, lab);
- DefineLabel(skip);
- CompleteLabel(skip);
- }
- return;
- case AstBinaryExpression::EQUAL_EQUAL:
- case AstBinaryExpression::NOT_EQUAL:
- // see if test against null
- if (left_type == this_control.null_type || right_type==this_control.null_type) {
- // arrange so right operand is null
- if (left_type == this_control.null_type) {
- temp = left;left = right;right = temp;
- left_type = left-> Type(); right_type = right-> Type();
- }
- EmitExpression(left);
- if (bp -> binary_tag == AstBinaryExpression::EQUAL_EQUAL) {
- EmitBranch(cond == true? OP_IFNULL : OP_IFNONNULL,lab);
- }
- else {
- EmitBranch(cond == true ? OP_IFNONNULL : OP_IFNULL,lab);
- }
- return;
- }
- // see if test against integer zero
- if (IsZero(left) || IsZero(right)) {
- // arrange so right operand is zero
- if (IsZero(left)) {
- temp = left;left = right;right = temp;
- left_type = left-> Type();right_type = right-> Type();
- }
- EmitExpression(left);
- if (bp -> binary_tag == AstBinaryExpression::EQUAL_EQUAL) {
- EmitBranch(cond == true? OP_IFEQ : OP_IFNE,lab);
- return;
- }
- else {
- EmitBranch(cond == true ? OP_IFNE : OP_IFEQ,lab);
- }
- return;
- }
- // see if test of integers
- if ((this_control.IsSimpleIntegerValueType(left_type)||left_type==this_control.boolean_type) &&
- (this_control.IsSimpleIntegerValueType(right_type)
- || right_type == this_control.boolean_type) ) {
- EmitExpression(left);
- EmitExpression(right);
- if (bp -> binary_tag == AstBinaryExpression::EQUAL_EQUAL) {
- EmitBranch(cond ? OP_IF_ICMPEQ : OP_IF_ICMPNE,lab);
- return;
- }
- else {
- EmitBranch(cond ? OP_IF_ICMPNE : OP_IF_ICMPEQ,lab);
- }
- return;
- }
- else if (IsReferenceType(left_type) && IsReferenceType(right_type)) {
- // else just do the comparison
- EmitExpression(left);
- EmitExpression(right);
- if (bp -> binary_tag == AstBinaryExpression::EQUAL_EQUAL) {
- EmitBranch(cond ? OP_IF_ACMPEQ : OP_IF_ACMPNE,lab);
- }
- else {
- EmitBranch(cond ? OP_IF_ACMPNE : OP_IF_ACMPEQ,lab);
- }
- return;
- }
- }
-
- // here if not comparison, comparison for non-integral numeric types, or
- // integral comparison for which no special casing needed.
- // Begin by dealing with non-comparisons
- switch(bp -> binary_tag) {
- case AstBinaryExpression::LESS:
- case AstBinaryExpression::LESS_EQUAL:
- case AstBinaryExpression::GREATER:
- case AstBinaryExpression::GREATER_EQUAL:
- case AstBinaryExpression::EQUAL_EQUAL:
- case AstBinaryExpression::NOT_EQUAL:
- break; // break to continue comparison processing
- default:
- // not a comparison, get the (necessarily boolean) value
- // of the expression and branch on the result
- EmitExpression(p);
- EmitBranch(cond ? OP_IFNE : OP_IFEQ, lab);
- return;
- }
- unsigned opcode = 0;
- unsigned int op_true, op_false;
- if (this_control.IsSimpleIntegerValueType(left_type)
- || left_type == this_control.boolean_type) {
- // we have already dealt with EQUAL_EQUAL and NOT_EQUAL for
- // integers, but still need to look for comparisons for which
- // one operand may be zero.
- if (IsZero(left)) {
- EmitExpression(right);
- switch(bp -> binary_tag) {
- case AstBinaryExpression::LESS: // if (0<x) same as if (x>0)
- op_true = OP_IFGT; op_false = OP_IFLE; break;
- case AstBinaryExpression::LESS_EQUAL: // if (0<=x) same as if (x>=0)
- op_true = OP_IFGE; op_false = OP_IFLT; break;
- case AstBinaryExpression::GREATER: // if (0>x) same as if (x<0)
- op_true = OP_IFLT; op_false = OP_IFGE; break;
- case AstBinaryExpression::GREATER_EQUAL: // if (0>=x) same as if (x<=0)
- op_true = OP_IFLE; op_false = OP_IFGT; break;
- }
- }
- else if (IsZero(right)) {
- EmitExpression(left);
- switch(bp -> binary_tag) {
- case AstBinaryExpression::LESS:
- op_true = OP_IFLT; op_false = OP_IFGE; break;
- case AstBinaryExpression::LESS_EQUAL:
- op_true = OP_IFLE; op_false = OP_IFGT; break;
- case AstBinaryExpression::GREATER:
- op_true = OP_IFGT; op_false = OP_IFLE; break;
- case AstBinaryExpression::GREATER_EQUAL:
- op_true = OP_IFGE; op_false = OP_IFLT; break;
- }
- }
- else {
- EmitExpression(left);
- EmitExpression(right);
- switch(bp -> binary_tag) {
- case AstBinaryExpression::LESS:
- op_true = OP_IF_ICMPLT; op_false = OP_IF_ICMPGE; break;
- case AstBinaryExpression::LESS_EQUAL:
- op_true = OP_IF_ICMPLE; op_false = OP_IF_ICMPGT; break;
- case AstBinaryExpression::GREATER:
- op_true = OP_IF_ICMPGT; op_false = OP_IF_ICMPLE; break;
- case AstBinaryExpression::GREATER_EQUAL:
- op_true = OP_IF_ICMPGE; op_false = OP_IF_ICMPLT; break;
- }
- }
- }
- else if (left_type == this_control.long_type) {
- EmitExpression(left);
- EmitExpression(right);
- opcode = OP_LCMP;
- // branch according to result value on stack
- switch (bp -> binary_tag) {
- case AstBinaryExpression::EQUAL_EQUAL:
- op_true = OP_IFEQ; op_false = OP_IFNE; break;
- case AstBinaryExpression::NOT_EQUAL:
- op_true = OP_IFNE; op_false = OP_IFEQ; break;
- case AstBinaryExpression::LESS:
- op_true = OP_IFLT; op_false = OP_IFGE; break;
- case AstBinaryExpression::LESS_EQUAL:
- op_true = OP_IFLE; op_false = OP_IFGT; break;
- case AstBinaryExpression::GREATER:
- op_true = OP_IFGT; op_false = OP_IFLE; break;
- case AstBinaryExpression::GREATER_EQUAL:
- op_true = OP_IFGE; op_false = OP_IFLT; break;
- }
- }
- else if (left_type == this_control.float_type) {
- EmitExpression(left);
- EmitExpression(right);
- switch (bp -> binary_tag) {
- case AstBinaryExpression::EQUAL_EQUAL:
- opcode = OP_FCMPL; op_true = OP_IFEQ; op_false = OP_IFNE; break;
- case AstBinaryExpression::NOT_EQUAL:
- opcode = OP_FCMPL; op_true = OP_IFNE; op_false = OP_IFEQ; break;
- case AstBinaryExpression::LESS:
- opcode = OP_FCMPG; op_true = OP_IFLT; op_false = OP_IFGE; break;
- case AstBinaryExpression::LESS_EQUAL:
- opcode = OP_FCMPG; op_true = OP_IFLE; op_false = OP_IFGT; break;
- case AstBinaryExpression::GREATER:
- opcode = OP_FCMPL; op_true = OP_IFGT; op_false = OP_IFLE; break;
- case AstBinaryExpression::GREATER_EQUAL:
- opcode = OP_FCMPL; op_true = OP_IFGE; op_false = OP_IFLT; break;
- }
- }
- else if (left_type == this_control.double_type) {
- EmitExpression(left);
- EmitExpression(right);
- switch (bp -> binary_tag) {
- case AstBinaryExpression::EQUAL_EQUAL:
- opcode = OP_DCMPL; op_true = OP_IFEQ; op_false = OP_IFNE; break;
- case AstBinaryExpression::NOT_EQUAL:
- opcode = OP_DCMPL; op_true = OP_IFNE; op_false = OP_IFEQ; break;
- case AstBinaryExpression::LESS:
- opcode = OP_DCMPG; op_true = OP_IFLT; op_false = OP_IFGE; break;
- case AstBinaryExpression::LESS_EQUAL:
- opcode = OP_DCMPG; op_true = OP_IFLE; op_false = OP_IFGT; break;
- case AstBinaryExpression::GREATER:
- opcode = OP_DCMPL; op_true = OP_IFGT; op_false = OP_IFLE; break;
- case AstBinaryExpression::GREATER_EQUAL:
- opcode = OP_DCMPL; op_true = OP_IFGE; op_false = OP_IFLT; break;
- }
- }
- else {
- chaos("comparison of unsupported type");
- }
- if (opcode) PutOp(opcode); // if need to emit comparison before branch
- EmitBranch (cond ? op_true: op_false, lab);
- }
-
- void ByteCode::EmitSynchronizedStatement(AstSynchronizedStatement * statement)
- {
- int var_index; // local variable index to save address of object
- int loc_index; // local variable index to save address
- int start_pc,end_pc;
- int exception_index,handler_pc;
- Label end_label;
- var_index = statement -> block -> block_symbol -> synchronized_variable_index;
- loc_index = var_index+1;
- EmitExpression(statement -> expression);
- StoreLocal(var_index, this_control.Object()); // save address of object
- LoadLocal(var_index, this_control.Object()); // load address of object onto stack
-
- PutOp(OP_MONITORENTER); // enter monitor associated with object
- start_pc = code_attribute -> code.Length(); // start pc
- (void) EmitBlockStatement(statement -> block, 1);
- LoadLocal(var_index, this_control.Object()); // load address of object onto stack
- PutOp(OP_MONITOREXIT);
- if (statement -> block -> NumStatements() > 0) {
- end_pc = last_op_pc;
- EmitBranch(OP_GOTO,end_label); // branch around exception handler
- // reach here if any
- // increment max_stack in case exception thrown while stack at greatest depth
- code_attribute -> max_stack++;
- handler_pc = code_attribute -> code.Length();
- LoadLocal(var_index, this_control.Object()); // load address of object onto stack
- PutOp(OP_MONITOREXIT);
- PutOp(OP_ATHROW);
- exception_index = code_attribute -> exception_table.NextIndex();
- code_attribute -> exception_table[exception_index].start_pc = start_pc;
- code_attribute -> exception_table[exception_index].end_pc = handler_pc;
- code_attribute -> exception_table[exception_index].handler_pc = handler_pc;
- code_attribute -> exception_table[exception_index].catch_type = 0;
- DefineLabel(monitor_labels[statement -> block -> nesting_level]);
- CompleteLabel(monitor_labels[statement -> block -> nesting_level]);
- StoreLocal(loc_index, this_control.Object()); // save return address
- LoadLocal(var_index, this_control.Object()); // load address of object onto stack
- PutOp(OP_MONITOREXIT);
- PutOp(OP_RET);
- PutU1(loc_index); // return using saved address
- DefineLabel(end_label);
- CompleteLabel(end_label);
- // EmitNop(1); // guarantee some PutOp after block in case
- // the synchronized statement is the last in the procedure.
- }
- }
-
- // JLS is Java Language Specification
- // JVM is Java Virtual Machine
- //
- // Expressions: Chapter 14 of JLS
-
- int ByteCode::EmitExpression(AstExpression *expression)
- {
- if (expression -> IsConstant()) {
- return LoadConstant(expression);
- }
- switch (expression -> kind) {
- case Ast::IDENTIFIER:
- if (expression -> SimpleNameCast() && expression -> SimpleNameCast() -> resolution_opt) {
- return EmitExpression(expression -> SimpleNameCast() -> resolution_opt);
- }
- return LoadSimple(GetLHSKind(expression, (MethodSymbol *)0),expression);
- case Ast::INTEGER_LITERAL:
- case Ast::LONG_LITERAL:
- case Ast::FLOATING_POINT_LITERAL:
- case Ast::DOUBLE_LITERAL:
- case Ast::TRUE_LITERAL:
- case Ast::FALSE_LITERAL:
- case Ast::STRING_LITERAL:
- case Ast::CHARACTER_LITERAL:
- return LoadConstant(expression);
- case Ast::THIS_EXPRESSION:
- case Ast::SUPER_EXPRESSION:
- PutOp(OP_ALOAD_0); // must be use
- return 1;
- case Ast::PARENTHESIZED_EXPRESSION:
- {
- AstParenthesizedExpression * pe =
- (AstParenthesizedExpression *) expression;
- return EmitExpression(expression -> ParenthesizedExpressionCast() -> expression);
- }
- case Ast::CLASS_CREATION:
- return EmitClassInstanceCreationExpression((AstClassInstanceCreationExpression *)expression, 1);
- case Ast::ARRAY_CREATION:
- return EmitArrayCreationExpression((AstArrayCreationExpression *)expression);
- case Ast::DIM:
- return EmitExpression(expression -> DimExprCast() -> expression);
- case Ast::DOT:
- {
- AstFieldAccess * field_access =(AstFieldAccess *)expression;
- return ((field_access -> IsClassAccess()) && (field_access -> resolution_opt))
- ? (ClassFile::type -> outermost_type -> ACC_INTERFACE()
- ? EmitExpression(field_access -> resolution_opt)
- : GenerateClassAccess(field_access))
- : EmitFieldAccess(field_access);
- }
- case Ast::CALL:
- return EmitMethodInvocation((AstMethodInvocation *)expression, 0);
- case Ast::ARRAY_ACCESS: // if seen alone this will be as RHS
- return EmitArrayAccessRHS((AstArrayAccess *) expression);
- case Ast::POST_UNARY:
- return EmitPostUnaryExpression((AstPostUnaryExpression *)expression,1);
- case Ast::PRE_UNARY:
- return EmitPreUnaryExpression((AstPreUnaryExpression *)expression,1);
- case Ast::CAST:
- {
- AstCastExpression * cast_expression = expression -> CastExpressionCast();
- if (cast_expression -> expression-> Type() -> Primitive())
- {
- // primitive types require casting
- return EmitCastExpression(cast_expression);
- }
- else {
- // not need to cast, just evaluate operand
- return EmitExpression(cast_expression -> expression);
- }
- }
-
- case Ast::CHECK_AND_CAST:
- return EmitCastExpression((AstCastExpression *)expression);
- case Ast::BINARY:
- return EmitBinaryExpression((AstBinaryExpression *)expression);
- case Ast::CONDITIONAL:
- return EmitConditionalExpression((AstConditionalExpression *)expression);
- case Ast::ASSIGNMENT:
- return EmitAssignmentExpression((AstAssignmentExpression *)expression,1);
- case Ast::NULL_LITERAL:
- PutOp(OP_ACONST_NULL);
- return 1;
- default:
- chaos("unknown expression kind");
- return 0; // even tho will not reach here
- }
- }
- void ByteCode::EmitArrayAccessLHS(AstArrayAccess *expression)
- {
- LoadReference(expression -> base);
- EmitExpression(expression -> expression);
- }
- int ByteCode::EmitArrayAccessRHS(AstArrayAccess *expression)
- {
- EmitArrayAccessLHS(expression); // get array address and index
- return LoadArrayElement(expression-> Type());
- }
-
- void ByteCode::EmitFieldAccessLHSBase(AstExpression * expression) {
- AstFieldAccess * field;
- AstSimpleName * simple_name;
- field = expression -> FieldAccessCast();
- if (field){
- if (field -> resolution_opt) {
- expression = field -> resolution_opt;
- }
- }
- else if (expression -> SimpleNameCast()) {
- simple_name = expression -> SimpleNameCast();
- if (simple_name -> resolution_opt) {
- expression = simple_name -> resolution_opt;
- }
- }
- VariableSymbol * sym = (VariableSymbol *) expression -> symbol;
- field = expression -> FieldAccessCast();
- if (field){
- EmitExpression(field -> base);
- }
- else if (expression -> SimpleNameCast()) {
- PutOp(OP_ALOAD_0); // get address of "this"
- }
- else {
- chaos("unexpected AssignmentExpressionField operand base type");
- }
- }
-
- void ByteCode::EmitFieldAccessLHS(AstExpression * expression)
- {
- EmitFieldAccessLHSBase(expression);
- PutOp(OP_DUP); // save base address of field for later store
- PutOp(OP_GETFIELD);
- ChangeStack(this_control.IsDoubleWordType(expression-> Type()) ? 1: 0);
- PutU2(GenerateFieldReference((VariableSymbol *) expression -> symbol));
- }
- void ByteCode::GenerateClassAccessMethod(MethodSymbol * msym) {
- // generate code for access method used to set class literal fields
- /* The code takes the form
- aload_0 load this
- invokestatic java/lang/Class.forName(String)java/lang/Class
- areturn return Class object for the class named by string
- // exception handler if forName fails
- astore_1 save exception
- new java.lang.NoClassDefFoundError
- dup save so can return
- aload_1 recover exception
- invokevirtual java.lang.Throwable.getMessage() to get error message
- invokenonvirtual <init> // invoke initializer
- athrow rethrow the exception
- */
-
- code_attribute -> max_locals = 2;
- PutOp(OP_ALOAD_0);
- PutOp(OP_INVOKESTATIC);
- ChangeStack(-1);
- PutU2(BuildMethodref(RegisterClass(U8S_java_SL_lang_SL_Class, strlen(U8S_java_SL_lang_SL_Class)),
- BuildNameAndType(RegisterUtf8(U8S_forName, strlen(U8S_forName)),
- RegisterUtf8(U8S_LP_Ljava_SL_lang_SL_String_SC_RP_Ljava_SL_lang_SL_Class_SC,
- strlen(U8S_LP_Ljava_SL_lang_SL_String_SC_RP_Ljava_SL_lang_SL_Class_SC)))));
- ChangeStack(1);
-
- PutOp(OP_ARETURN);
- PutOp(OP_ASTORE_1);
- PutOp(OP_NEW);
- PutU2(RegisterClass(U8S_java_SL_lang_SL_NoClassDefFoundError, strlen(U8S_java_SL_lang_SL_NoClassDefFoundError)));
- PutOp(OP_DUP);
- PutOp(OP_ALOAD_1);
- PutOp(OP_INVOKEVIRTUAL);
- ChangeStack(-1);
- PutU2(BuildMethodref(RegisterClass(U8S_java_SL_lang_SL_Throwable, strlen(U8S_java_SL_lang_SL_Throwable)),
- BuildNameAndType(
- RegisterUtf8(U8S_getMessage, strlen(U8S_getMessage)),
- RegisterUtf8(U8S_LP_RP_Ljava_SL_lang_SL_String_SC, strlen(U8S_LP_RP_Ljava_SL_lang_SL_String_SC)))));
- ChangeStack(1);
-
- PutOp(OP_INVOKENONVIRTUAL);
- ChangeStack(-1);
- PutU2(BuildMethodref(RegisterClass(U8S_java_SL_lang_SL_NoClassDefFoundError, strlen(U8S_java_SL_lang_SL_NoClassDefFoundError)),
- BuildNameAndType(
- RegisterUtf8(U8S_LT_init_GT_, strlen(U8S_LT_init_GT_)),
- RegisterUtf8(U8S_LP_Ljava_SL_lang_SL_String_SC_RP_V, strlen(U8S_LP_Ljava_SL_lang_SL_String_SC_RP_V)))));
- ChangeStack(1);
- PutOp(OP_ATHROW);
- code_attribute -> max_stack = 3;
- int exception_index = code_attribute -> exception_table.NextIndex();
- code_attribute -> exception_table[exception_index].start_pc = 0;
- code_attribute -> exception_table[exception_index].end_pc = 5; // DS 11 feb
- code_attribute -> exception_table[exception_index].handler_pc = 5;
- code_attribute -> exception_table[exception_index].catch_type =
- RegisterClass(U8S_java_SL_lang_SL_ClassNotFoundException, strlen(U8S_java_SL_lang_SL_ClassNotFoundException));
-
- }
- int ByteCode::GenerateClassAccess(AstFieldAccess * field_access)
- { // here to generate code to dymanically initialize the field for a class literal and then return its value
- Label lab1,lab2;
- if (field_access -> symbol -> VariableCast()) {
- // simple case in immediate environment, can use field on both left and right
-
- //(TypeSymbol * type)
- // evaluate X.class literal. If X is a primitive type, this is a predefined field;
- // otherwise, we must create a new synthetic field to hold the desired result and
- // initialize it at runtime.
- /* generate
- getstatic class_field load class field
- ifnull lab1 branch if not yet set
- get class_field here if set, return value
- goto lab2
- lab1: here to initialize the field
- load class_constant get name of class
- invokestatic invoke generated method to get class_field desired value
- dup save value so can return it
- put class_field initialize the field
- lab2:
- */
- VariableSymbol * sym = field_access -> symbol -> VariableCast();
-
- PutOp(OP_GETSTATIC);
- PutU2(GenerateFieldReference(sym));
- ChangeStack(1);
- EmitBranch(OP_IFNULL, lab1);
- PutOp(OP_GETSTATIC);
- PutU2(GenerateFieldReference(sym));
- ChangeStack(1);
- EmitBranch(OP_GOTO, lab2);
- DefineLabel(lab1);
- // generate load of constant naming the class
- LoadLiteral(field_access -> base-> Type() -> ClassLiteralName(), this_control.String());
- PutOp(OP_INVOKESTATIC);
- CompleteCall(class_literal_method, 1, 0);
- PutOp(OP_DUP);
- PutOp(OP_PUTSTATIC);
- PutU2(GenerateFieldReference(sym));
- ChangeStack(-1);
- }
- else {
- // here in nested case, where must invoke access methods for the field
- VariableSymbol * sym = field_access -> symbol -> VariableCast();
- MethodSymbol * read_symbol = field_access -> symbol -> MethodCast();
- MethodSymbol * write_symbol = field_access -> resolution_opt -> symbol -> MethodCast();
-
- AstMethodInvocation * resolve = field_access -> resolution_opt -> MethodInvocationCast();
- u2 read_ref, write_ref;
- // need load this for class with method
- // if the next statement read field_access -> resolution_opt -> symbol = read_method, then
- // generating code for that expression tree would give us what we want
- field_access -> resolution_opt -> symbol = read_symbol;
- PutOp(OP_INVOKESTATIC);
- read_ref = BuildMethodref(RegisterClass(read_symbol -> containing_type -> fully_qualified_name),
- BuildNameAndType(
- RegisterUtf8(read_symbol -> ExternalIdentity() -> Utf8_literal),
- RegisterUtf8(read_symbol -> signature)));
- PutU2(read_ref);
- ChangeStack(1);
-
- EmitBranch(OP_IFNULL, lab1);
- PutOp(OP_INVOKESTATIC);
- PutU2(read_ref);
- ChangeStack(1);
- EmitBranch(OP_GOTO, lab2);
- DefineLabel(lab1);
- // generate load of constant naming the class
- LoadLiteral(field_access -> base-> Type() -> ClassLiteralName(), this_control.String());
- PutOp(OP_INVOKESTATIC);
- CompleteCall(class_literal_method, 1, 0);
- PutOp(OP_DUP);
- PutOp(OP_INVOKESTATIC);
- write_ref = BuildMethodref(RegisterClass(write_symbol -> containing_type -> fully_qualified_name),
- BuildNameAndType(
- RegisterUtf8(write_symbol -> ExternalIdentity() -> Utf8_literal),
- RegisterUtf8(write_symbol -> signature)));
- PutU2(write_ref);
- ChangeStack(-1); // to indicate argument popped
-
- }
- DefineLabel(lab2);
- CompleteLabel(lab1);
- CompleteLabel(lab2);
- return 1; // return one-word (reference) result
- }
-
- int ByteCode::EmitArrayCreationExpression(AstArrayCreationExpression *expression)
- {
- // see also OP_MULTINEWARRAY
- int dims;
- if (expression -> array_initializer_opt) {
- InitializeArray(expression-> Type(), expression -> array_initializer_opt);
- }
- else {
- dims = expression -> NumDimExprs();
- // need to push value of dimension(s)
- for (int i = 0;i < dims;i++) {
- AstDimExpr *d_expr = expression -> DimExpr(i);
- EmitExpression(d_expr -> expression);
- }
- EmitNewArray(dims, expression-> Type());
- }
- return 1;
- }
-
- int ByteCode::EmitAssignmentExpression(AstAssignmentExpression *expression,int need_value)
- {
- // ASSIGNMENT
- int kind;
- int opc;
- int need_cast=0;
- VariableSymbol * sym;
- AstExpression * left_hand_side;
- TypeSymbol * expression_type = expression-> Type();
- TypeSymbol * expression_expression_type = expression -> expression-> Type();
- TypeSymbol * left_type;
- TypeSymbol * dest_type;
- TypeSymbol * cast_type;
- TypeSymbol * op_type;
- int stack_words = 0;
- if (expression -> left_hand_side -> CastExpressionCast()) {
- need_cast = 1;
- cast_type = expression -> left_hand_side -> CastExpressionCast()-> Type();
- left_hand_side = expression -> left_hand_side -> CastExpressionCast() -> expression;
- op_type = cast_type;
- dest_type = expression -> left_hand_side-> Type();;
- }
- else {
- left_hand_side = expression -> left_hand_side;
- op_type = expression_type;
- }
- left_type = left_hand_side-> Type();
- kind = GetLHSKind(expression -> left_hand_side, expression -> write_method);
- if (expression -> assignment_tag == AstAssignmentExpression::EQUAL) {
- switch(kind) {
- case LHS_ARRAY:
- EmitArrayAccessLHS(left_hand_side -> ArrayAccessCast()); // lhs must be array access
- break;
- case LHS_FIELD:
- EmitFieldAccessLHSBase(left_hand_side); // load base for field access
- break;
- case LHS_CLASS_METHOD:
- // need to load address of object, obtained from resolution
- ResolveAccess(left_hand_side, 0); // just get address
- break;
- case LHS_STATIC_METHOD:
- // nothing to do for static method at this point
- break;
- }
- EmitExpression(expression -> expression);
- }
- else {
- // here for compound assignment. Get the left operand, saving any information necessary to
- // update its value on the stack below the value.
- switch(kind) {
- case LHS_ARRAY:
- EmitArrayAccessLHS(left_hand_side -> ArrayAccessCast()); // lhs must be array access
- PutOp(OP_DUP2); // save base and index for later store
- // load current value
- (void) LoadArrayElement(expression_type);
- break;
- case LHS_FIELD:
- EmitFieldAccessLHS(left_hand_side);
- break;
- case LHS_LOCAL:
- case LHS_STATIC:
- (void) LoadSimple(kind,left_hand_side);
- ChangeStack(this_control.IsDoubleWordType(left_type) ? 1: 0); // CHECK_THIS? Is this really necessary
- break;
- case LHS_CLASS_METHOD:
- // need to load address of object, obtained from resolution, saving a copy on the stack
- ResolveAccess(left_hand_side, 1); // get address and value
- break;
- case LHS_STATIC_METHOD:
- // get value by invoking the appropriate resolution
- EmitExpression(left_hand_side -> SimpleNameCast() -> resolution_opt); // get value
- break;
- }
-
- if (expression -> assignment_tag ==AstAssignmentExpression::PLUS_EQUAL
- && left_type == this_control.String()) {
- // Here for string concatenation.
- EmitStringBuffer();
- PutOp(OP_SWAP); // swap address if buffer and string to update.
- EmitStringAppendMethod(this_control.String());
- AppendString(expression -> expression);
- EmitCallStringToString();
- }
- else {
- // Here for operation other than string concatenation. Determine the opcode to use.
- if (this_control.IsSimpleIntegerValueType(op_type)||
- op_type == this_control.boolean_type){
- switch (expression -> assignment_tag) {
- case AstAssignmentExpression::STAR_EQUAL: opc = OP_IMUL; break;
- case AstAssignmentExpression::SLASH_EQUAL: opc = OP_IDIV; break;
- case AstAssignmentExpression::MOD_EQUAL: opc = OP_IREM; break;
- case AstAssignmentExpression::PLUS_EQUAL: opc = OP_IADD; break;
- case AstAssignmentExpression::MINUS_EQUAL: opc = OP_ISUB; break;
- case AstAssignmentExpression::LEFT_SHIFT_EQUAL: opc = OP_ISHL; break;
- case AstAssignmentExpression::RIGHT_SHIFT_EQUAL: opc = OP_ISHR; break;
- case AstAssignmentExpression::UNSIGNED_RIGHT_SHIFT_EQUAL: opc = OP_IUSHR; break;
- case AstAssignmentExpression::AND_EQUAL: opc = OP_IAND; break;
- case AstAssignmentExpression::IOR_EQUAL: opc = OP_IOR; break;
- case AstAssignmentExpression::XOR_EQUAL: opc = OP_IXOR; break;
- }
- }
- else if (op_type == this_control.long_type){
- switch (expression -> assignment_tag) {
- case AstAssignmentExpression::STAR_EQUAL: opc = OP_LMUL; break;
- case AstAssignmentExpression::SLASH_EQUAL: opc = OP_LDIV; break;
- case AstAssignmentExpression::MOD_EQUAL: opc = OP_LREM; break;
- case AstAssignmentExpression::PLUS_EQUAL: opc = OP_LADD; break;
- case AstAssignmentExpression::MINUS_EQUAL: opc = OP_LSUB; break;
- case AstAssignmentExpression::LEFT_SHIFT_EQUAL: opc = OP_LSHL; break;
- case AstAssignmentExpression::RIGHT_SHIFT_EQUAL: opc = OP_LSHR; break;
- case AstAssignmentExpression::UNSIGNED_RIGHT_SHIFT_EQUAL: opc = OP_LUSHR; break;
- case AstAssignmentExpression::AND_EQUAL: opc = OP_LAND; break;
- case AstAssignmentExpression::IOR_EQUAL: opc = OP_LOR; break;
- case AstAssignmentExpression::XOR_EQUAL: opc = OP_LXOR; break;
- }
- }
- else if (op_type == this_control.float_type) {
- switch (expression -> assignment_tag) {
- case AstAssignmentExpression::STAR_EQUAL: opc = OP_FMUL; break;
- case AstAssignmentExpression::SLASH_EQUAL: opc = OP_FDIV; break;
- case AstAssignmentExpression::MOD_EQUAL: opc = OP_FREM; break;
- case AstAssignmentExpression::PLUS_EQUAL: opc = OP_FADD; break;
- case AstAssignmentExpression::MINUS_EQUAL: opc = OP_FSUB; break;
- }
- }
- else if (op_type == this_control.double_type) {
- switch (expression -> assignment_tag) {
- case AstAssignmentExpression::STAR_EQUAL: opc = OP_DMUL; break;
- case AstAssignmentExpression::SLASH_EQUAL: opc = OP_DDIV; break;
- case AstAssignmentExpression::MOD_EQUAL: opc = OP_DREM; break;
- case AstAssignmentExpression::PLUS_EQUAL: opc = OP_DADD; break;
- case AstAssignmentExpression::MINUS_EQUAL: opc = OP_DSUB; break;
- }
- }
-
- // convert value to desired type if necessary
- if (need_cast) {
- EmitCast(cast_type,left_type);
- }
-
- EmitExpression(expression -> expression);
-
- PutOp(opc);
-
- if (need_cast) { // now cast result back to type of result
- EmitCast(left_type, cast_type);
- }
- }
- }
- // Update left operand, saving value of right operand if it is needed.
- switch(kind) {
- case LHS_ARRAY:
- if (need_value) {
- if (this_control.IsDoubleWordType(left_type)) {
- PutOp(OP_DUP2_X2);
- }
- else PutOp(OP_DUP_X2);
- }
- StoreArrayElement(expression_type);
- break;
- case LHS_FIELD:
- case LHS_CLASS_METHOD:
- if (need_value) {
- if (this_control.IsDoubleWordType(left_type)) {
- PutOp(OP_DUP2_X1);
- }
- else PutOp(OP_DUP_X1);
- }
- if (kind==LHS_CLASS_METHOD) {
- stack_words = this_control.IsDoubleWordType(left_type) ? 2: 1;
- PutOp(OP_INVOKEVIRTUAL);
- CompleteCall(expression -> write_method, stack_words, 0);
- }
- else {
- StoreField(left_hand_side);
- }
- break;
- case LHS_LOCAL:
- case LHS_STATIC:
- case LHS_STATIC_METHOD:
- if (need_value) {
- if (this_control.IsDoubleWordType(left_type)) {
- PutOp(OP_DUP2);
- }
- else PutOp(OP_DUP);
- }
- if (kind==LHS_STATIC_METHOD) {
- stack_words = this_control.IsDoubleWordType(left_type) ? 2: 1;
- PutOp(OP_INVOKESTATIC);
- CompleteCall(expression -> write_method, stack_words, 0);
- }
- else {
- StoreSimple(kind,left_hand_side);
- }
-
- break;
- }
- return GetTypeWords(expression_type);
- }
-
- // Similar code patterns are used for the ordered comparisons
- int ByteCode::EmitBinaryExpression(AstBinaryExpression *expression)
- {
- // BINARY
- switch (expression -> binary_tag) { // process boolean-results first
- case AstBinaryExpression::OR_OR:
- case AstBinaryExpression::AND_AND:
- case AstBinaryExpression::LESS:
- case AstBinaryExpression::LESS_EQUAL:
- case AstBinaryExpression::GREATER:
- case AstBinaryExpression::GREATER_EQUAL:
- case AstBinaryExpression::EQUAL_EQUAL:
- case AstBinaryExpression::NOT_EQUAL: {
- Label lab1,lab2;
- EmitBranchIfExpression(expression,true,lab1);
- PutOp(OP_ICONST_0); // push false
- EmitBranch(OP_GOTO,lab2);
- DefineLabel(lab1);
- PutOp(OP_ICONST_1); // push false
- DefineLabel(lab2);
- CompleteLabel(lab1);
- CompleteLabel(lab2);
- }
- return 1;
- }
- if (expression -> binary_tag == AstBinaryExpression::INSTANCEOF) {
- TypeSymbol * instanceof_type = expression -> right_expression-> Type();
- EmitExpression(expression -> left_expression);
- PutOp(OP_INSTANCEOF);
- if (instanceof_type -> num_dimensions) {
- PutU2(RegisterClass(instanceof_type -> signature));
- }
- else {
- PutU2(RegisterClass(instanceof_type -> fully_qualified_name));
- }
- return 1;
- }
- // special case string concatenation
- if (expression -> binary_tag == AstBinaryExpression::PLUS && (IsReferenceType(expression -> left_expression-> Type())) ||
- IsReferenceType(expression -> right_expression-> Type())) {
- ConcatenateString(expression);
- return 1;
- }
- #ifdef TBSL
- // debug this later (DS 19 nov 96)
- // try to simplify if one operand known to be zero.
- if (isZero(expression -> left_expression)) {
- TypeSymbol * right_type = expression -> right_expression-> Type();
- switch (expression -> binary_tag) {
- case AstBinaryExpression::PLUS:
- case AstBinaryExpression::IOR:
- case AstBinaryExpression::XOR:
- // here for cases that simplify to the right operand
- EmitExpression(expression -> right_expression);
- return;
- case AstBinaryExpression::STAR:
- case AstBinaryExpression::AND:
- case AstBinaryExpression::LEFT_SHIFT:
- case AstBinaryExpression::RIGHT_SHIFT:
- case AstBinaryExpression::UNSIGNED_RIGHT_SHIFT:
- // here for cases that evaluate to zero
- if (this_control.IsSimpleIntegerValueType(right_type)) {
- LoadShort(0);
- }
- else if (right_type == this_control.long_type) {
- PutOp(OP_LCONST_0);
- }
- else if (right_type == this_control.float_type) {
- PutOp(OP_FCONST_0);
- }
- else if (right_type == this_control.double_type) {
- PutOp(OP_DCONST_0);
- }
- else chaos("unexpected type in expression simplification");
- return GetTypeWords(right_type);
-
- case AstBinaryExpression::MINUS:
- // 0 - x is negation of x
- EmitExpression(expression -> right_expression);
- if (this_control.IsSimpleIntegerValueType(right_type)) {
- PutOp(OP_INEG);
- }
- else if (right_type == this_control.long_type) {
- PutOp(OP_LNEG);
- }
- else if (right_type == this_control.float_type) {
- PutOp(OP_FNEG);
- }
- else if (right_type == this_control.double_type) {
- PutOp(OP_DNEG);
- }
- else chaos("unexpected type in expression simplification");
- return 1;
- }
- }
-
-
- if (isZero(expression -> right_expression)) {
- TypeSymbol * left_type = expression -> left_expression-> Type();
- switch (expression->binary_tag) {
- case AstBinaryExpression::PLUS:
- case AstBinaryExpression::MINUS:
- case AstBinaryExpression::IOR:
- case AstBinaryExpression::XOR:
- case AstBinaryExpression::LEFT_SHIFT:
- case AstBinaryExpression::RIGHT_SHIFT:
- case AstBinaryExpression::UNSIGNED_RIGHT_SHIFT:
- // here for cases that simplify to the left operand
- EmitExpression(expression->left_expression);
- return;
- case AstBinaryExpression::STAR:
- case AstBinaryExpression::AND:
- // here for cases that evaluate to zero
- if (this_control.IsSimpleIntegerValueType(left_type)) {
- LoadShort(0);
- }
- else if (left_type == this_control.long_type) {
- PutOp(OP_LCONST_0);
- }
- else if (left_type == this_control.float_type) {
- PutOp(OP_FCONST_0);
- }
- else if (left_type == this_control.double_type) {
- PutOp(OP_DCONST_0);
- }
- else chaos("unexpected type in expression simplification");
- return;
- }
-
- }
- #endif
-
- EmitExpression(expression -> left_expression);
- EmitExpression(expression -> right_expression);
-
- switch (expression -> binary_tag) {
- case AstBinaryExpression::STAR:
- EmitBinaryOp(expression, OP_IMUL, OP_LMUL, OP_FMUL, OP_DMUL);
- break;
- case AstBinaryExpression::SLASH:
- EmitBinaryOp(expression, OP_IDIV, OP_LDIV, OP_FDIV, OP_DDIV);
- break;
- case AstBinaryExpression::MOD:
- EmitBinaryOp(expression, OP_IREM, OP_LREM, OP_FREM, OP_DREM);
- break;
- case AstBinaryExpression::PLUS:
- EmitBinaryOp(expression, OP_IADD, OP_LADD, OP_FADD, OP_DADD);
- break;
- case AstBinaryExpression::MINUS:
- EmitBinaryOp(expression, OP_ISUB, OP_LSUB, OP_FSUB, OP_DSUB);
- break;
- case AstBinaryExpression::LEFT_SHIFT:
- EmitBinaryOp(expression, OP_ISHL, OP_LSHL, 0, 0);
- break;
- case AstBinaryExpression::RIGHT_SHIFT:
- EmitBinaryOp(expression, OP_ISHR, OP_LSHR, 0, 0);
- break;
- case AstBinaryExpression::UNSIGNED_RIGHT_SHIFT:
- EmitBinaryOp(expression, OP_IUSHR, OP_LUSHR, 0, 0);
- break;
- // case AstBinaryExpression::INSTANCEOF:
- // EmitInstanceofExpression((AstInstanceofExpression *)expression);
- // break;
- case AstBinaryExpression::AND:
- EmitBinaryOp(expression, OP_IAND, OP_LAND, 0, 0);
- break;
- case AstBinaryExpression::XOR:
- EmitBinaryOp(expression, OP_IXOR, OP_LXOR, 0, 0);
- break;
- case AstBinaryExpression::IOR:
- EmitBinaryOp(expression, OP_IOR, OP_LOR, 0, 0);
- break;
- default:
- chaos("binary unknown tag");
- }
- return GetTypeWords(expression-> Type());
- }
-
-
- void ByteCode::EmitBinaryOp(AstBinaryExpression *expression, int iop, int lop, int fop, int dop)
- {
- int opc = 0;
- TypeSymbol * type = expression -> left_expression-> Type();
- // binary PutOp
- if (this_control.IsSimpleIntegerValueType(type)
- || type == this_control.boolean_type) opc = iop;
- else if (type == this_control.long_type) opc = lop;
- else if (type == this_control.float_type) opc = fop;
- else if (type == this_control.double_type) opc = dop;
- if (opc == 0) chaos(" * undefined on this type");
- PutOp(opc);
-
- }
- int ByteCode::EmitCastExpression(AstCastExpression *expression) {
- TypeSymbol * dest_type = expression-> Type();
- TypeSymbol * source_type = expression -> expression-> Type();
- // convert from numeric type src to destination type dest
- EmitExpression(expression -> expression);
- EmitCast(dest_type,source_type);
- return GetTypeWords(dest_type);
- }
- void ByteCode::EmitCast(TypeSymbol * dest_type, TypeSymbol * source_type)
- {
- if (dest_type == source_type) return; // done if nothing to do
- if (this_control.IsSimpleIntegerValueType(source_type)) {
- if (dest_type == this_control.long_type) PutOp(OP_I2L);
- else if (dest_type == this_control.float_type) PutOp(OP_I2F);
- else if (dest_type == this_control.double_type) PutOp(OP_I2D);
- else if (dest_type == this_control.char_type) PutOp(OP_I2C);
- else if (dest_type == this_control.byte_type) PutOp(OP_I2B);
- else if (dest_type == this_control.short_type) PutOp(OP_I2S);
- else if (dest_type == this_control.int_type); // no conversion needed
- else chaos("unsupported conversion");
- }
- else if (source_type == this_control.long_type) {
- if (this_control.IsSimpleIntegerValueType(dest_type)) {
- PutOp(OP_L2I);
- if (dest_type == this_control.char_type) PutOp(OP_I2C);
- else if (dest_type == this_control.byte_type) PutOp(OP_I2B);
- else if (dest_type == this_control.short_type) PutOp(OP_I2S);
- }
- else if (dest_type == this_control.float_type) PutOp(OP_L2F);
- else if (dest_type == this_control.double_type) PutOp(OP_L2D);
- else chaos("unsupported conversion");
- }
- else if (source_type == this_control.float_type) {
- if (this_control.IsSimpleIntegerValueType(dest_type)) {
- PutOp(OP_F2I);
- if (dest_type == this_control.char_type) PutOp(OP_I2C);
- else if (dest_type == this_control.byte_type) PutOp(OP_I2B);
- else if (dest_type == this_control.short_type) PutOp(OP_I2S);
- }
-
- else if (dest_type == this_control.long_type) PutOp(OP_F2L);
- else if (dest_type == this_control.double_type) PutOp(OP_F2D);
- else chaos("unsupported conversion");
- }
- else if (source_type == this_control.double_type) {
- if (this_control.IsSimpleIntegerValueType(dest_type)) {
- PutOp(OP_D2I);
- if (dest_type == this_control.char_type) PutOp(OP_I2C);
- else if (dest_type == this_control.byte_type) PutOp(OP_I2B);
- else if (dest_type == this_control.short_type) PutOp(OP_I2S);
- }
- else if (dest_type == this_control.long_type) PutOp(OP_D2L);
- else if (dest_type == this_control.float_type) PutOp(OP_D2F);
- else chaos("unsupported conversion");
- }
- else if (source_type == this_control.null_type) {
- //op(OP_ACONST_NULL);
- }
- else { // generate check cast instruction
- // it is possible to evaluate many of these at compile time
- if (dest_type -> num_dimensions) {
- PutOp(OP_CHECKCAST);
- PutU2(RegisterClass(dest_type -> signature));
- }
- else {
- PutOp(OP_CHECKCAST);
- PutU2(RegisterClass(dest_type -> fully_qualified_name));
- }
- }
- }
-
- int ByteCode::EmitClassInstanceCreationExpression(AstClassInstanceCreationExpression *expression, int need_value)
- {
- MethodSymbol * constructor = (MethodSymbol *) expression -> class_type -> symbol;
- TypeSymbol * type = expression-> Type();
- int stack_words = 0;
- Label lab1;
- PutOp(OP_NEW);
- PutU2(RegisterClass(type -> fully_qualified_name));
- if (need_value) PutOp(OP_DUP); // save address of new object for constructor
- // call constructor
- // pass address of object explicitly passed to new if specified.
- if (expression -> base_opt) {
- stack_words += EmitExpression(expression -> base_opt);
- PutOp(OP_DUP);
- EmitBranch(OP_IFNONNULL, lab1);
- // need to test for null, raising NullPointerException if so. So just do athrow
- PutOp(OP_ACONST_NULL);
- PutOp(OP_ATHROW);
- DefineLabel(lab1);
- CompleteLabel(lab1);
- }
-
- for (int i=0; i < expression -> NumLocalArguments();i++) {
- stack_words += EmitExpression((AstExpression *) expression -> LocalArgument(i));
- }
- for (int k=0; k < expression -> NumArguments();k++) {
- stack_words += EmitExpression((AstExpression *) expression -> Argument(k));
- }
- PutOp(OP_INVOKENONVIRTUAL);
- ChangeStack(-stack_words);
- if (constructor -> constant_pool_index == 0 || constructor -> constant_pool_class!=class_id) { // build method ref for method
- constructor -> constant_pool_index = BuildMethodref(
- RegisterClass(type -> fully_qualified_name),
- BuildNameAndType(
- RegisterUtf8(this_control.init_name_symbol -> Utf8_literal),
- RegisterUtf8(constructor -> signature)));
- constructor -> constant_pool_class = class_id;
- }
-
- PutU2(constructor -> constant_pool_index);
- return 1;
- }
-
- int ByteCode::EmitConditionalExpression(AstConditionalExpression *expression)
- {
- Label lab1,lab2;
- EmitBranchIfExpression(expression -> test_expression, false, lab1);
- EmitExpression(expression -> true_expression);
- EmitBranch(OP_GOTO,lab2);
- DefineLabel(lab1);
- EmitExpression(expression -> false_expression);
- DefineLabel(lab2);
- CompleteLabel(lab1);
- CompleteLabel(lab2);
- return GetTypeWords(expression -> true_expression-> Type());
- }
-
- int ByteCode::EmitFieldAccess(AstFieldAccess *expression)
- {
- AstExpression * p = expression -> base;
- VariableSymbol * sym = expression -> symbol -> VariableCast();
- TypeSymbol * expression_type = expression-> Type();
- if (expression -> IsConstant()) {
- if (sym -> ACC_STATIC()) {
- if (!( p -> symbol -> TypeCast() || p -> symbol -> VariableCast())) {
- EmitExpression(p);
- PutOp(OP_POP);
- }
- }
- return LoadConstant(expression);
- }
- if (expression -> resolution_opt) { // resolve reference to private field in parent
- return EmitExpression(expression -> resolution_opt);
- }
- if (p-> Type() -> IsArray() && sym -> ExternalIdentity() == this_control.length_name_symbol){
- EmitExpression(p);
- PutOp(OP_ARRAYLENGTH);
- return 1;
- }
- if (sym -> ACC_STATIC()) {
- if (!( p -> symbol -> TypeCast() || p -> symbol -> VariableCast())) {
- EmitExpression(p);
- PutOp(OP_POP);
- }
- PutOp(OP_GETSTATIC);
- ChangeStack(this_control.IsDoubleWordType(expression_type) ? 2: 1);
- }
- else {
- EmitExpression(p); // get base
- PutOp(OP_GETFIELD);
- ChangeStack(this_control.IsDoubleWordType(expression_type) ? 1: 0);
- }
- PutU2(GenerateFieldReference(sym));
- return GetTypeWords(expression_type);
- }
-
- void ByteCode::EmitCloneArray(AstMethodInvocation *expression)
- {
- // generate code corresponding to
- // try {
- // evaluate super.clone();
- // } catch (CloneNotSupportedException e) {
- // throw new InternalError(e.getMessage());
- // }
- MethodSymbol * msym = (MethodSymbol *) expression -> symbol;
- TypeSymbol * res_type = expression-> Type(); // result type
- AstFieldAccess * field;
- int start_pc,end_pc;
- Label end_label;
- int exception_index;
- // msym is clone_name_symbol, indicating array clone
- // use clone() in java/lang/Object.
- start_pc = code_attribute -> code.Length();
- field = expression -> method -> FieldAccessCast();
- if (field) {
- EmitExpression(field -> base);
- }
- else {
- chaos("field access expected in array clone");
- }
- PutOp(OP_INVOKEVIRTUAL);
- // ChangeStack(-stack_words);
- PutU2(RegisterMethod(METHOD_CLONE));
- EmitBranch(OP_GOTO, end_label);
- end_pc = code_attribute -> code.Length();
- // indicate that we use at least 2 local variables (this and the exception)
- if (code_attribute -> max_locals < 2)
- code_attribute -> max_locals = 2; // CSA fix 08-dec-1998 for PR 294
- // start handler
- // can't count next StoreLocal as pop since in handler
- ChangeStack(1);
- StoreLocal(1, this_control.Object());
- PutOp(OP_NEW);
- PutU2(RegisterClass(U8S_java_SL_lang_SL_InternalError, strlen(U8S_java_SL_lang_SL_InternalError)));
- PutOp(OP_DUP);
- LoadLocal(1, this_control.Object());
- PutOp(OP_INVOKEVIRTUAL);
- PutU2(RegisterMethod(METHOD_CLONE_GETMESSAGE));
- PutOp(OP_INVOKENONVIRTUAL);
- PutU2(RegisterMethod(METHOD_CLONE_INIT));
- PutOp(OP_ATHROW);
- DefineLabel(end_label);
- CompleteLabel(end_label);
-
- exception_index = code_attribute -> exception_table.NextIndex();
- code_attribute -> exception_table[exception_index].start_pc = start_pc;
- code_attribute -> exception_table[exception_index].end_pc = end_pc;
- code_attribute -> exception_table[exception_index].handler_pc = end_pc;
- // "java/lang/CloneNotSupportedException"
- code_attribute -> exception_table[exception_index].catch_type =
- RegisterClass(U8S_java_SL_lang_SL_CloneNotSupportedException, strlen(U8S_java_SL_lang_SL_CloneNotSupportedException));
-
- }
-
- int ByteCode::EmitMethodInvocation(AstMethodInvocation *expression, int copy_base)
- {
- MethodSymbol * msym = (MethodSymbol *) expression -> symbol;
- AstSimpleName * simple_name;
- TypeSymbol * res_type = expression-> Type(); // result type
- int is_private = msym -> ACC_PRIVATE();
- int is_static = msym -> ACC_STATIC();
- int is_super=0; // set if super call
- int is_interface = msym -> containing_type -> ACC_INTERFACE();
- AstFieldAccess * field;
- int stack_words = 0; // words on stack needed for arguments
- if (msym -> ExternalIdentity() == this_control.clone_name_symbol) {
- if (msym -> containing_type -> IsArray()) {
- EmitCloneArray(expression);
- return GetTypeWords(res_type);
- }
- #ifdef TBSL
- else {
- chaos(" clone not yet supported");
- }
- #endif
- }
- if (is_static) {
- if (expression -> method -> FieldAccessCast()) {
- field = expression -> method -> FieldAccessCast();
- if (field -> base -> MethodInvocationCast()) {
- (void) EmitMethodInvocation(field -> base -> MethodInvocationCast(), 0);
- PutOp(OP_POP); // discard value (only evaluating for side effect)
- }
-
- }
- }
- else {
- field = expression -> method -> FieldAccessCast();
- if (field) {
- AstFieldAccess *sub_field_access = field -> base -> FieldAccessCast();
-
- if (field -> base -> SuperExpressionCast() || (sub_field_access && sub_field_access -> IsSuperAccess())) {
- is_super=1;
- }
- if (field -> base -> MethodInvocationCast()) {
- (void) EmitMethodInvocation(field -> base -> MethodInvocationCast(), 0);
- }
- else {
- EmitExpression(field -> base);
- }
- }
- else if (expression -> method -> SimpleNameCast()) {
- simple_name = expression -> method -> SimpleNameCast();
- if (simple_name -> resolution_opt) { // use resolution if available
- (void) EmitExpression(simple_name -> resolution_opt);
- }
- else {
- // must be field of current object, so load this
- PutOp(OP_ALOAD_0);
- }
- }
- else {
- chaos("unexpected argument to field access");
- }
-
- }
- if (!is_static && copy_base) { // if need to save object ref for method invocation
- PutOp(OP_DUP);
- }
- for (int i=0; i < expression -> NumArguments();i++) {
- stack_words += EmitExpression((AstExpression *) expression -> Argument(i));
- }
- PutOp(msym -> ACC_STATIC() ? OP_INVOKESTATIC
- : (is_super | is_private) ? OP_INVOKENONVIRTUAL
- : is_interface ? OP_INVOKEINTERFACE
- : OP_INVOKEVIRTUAL);
- CompleteCall(msym,stack_words, is_interface);
- return GetTypeWords(res_type);
- }
- void ByteCode::CompleteCall(MethodSymbol * msym,int stack_words, int is_interface)
- {
- TypeSymbol * res_type = msym-> Type();
- ChangeStack(-stack_words);
- // need to get method index, the constant_pool index for a
- // reference to this method (a Methodref);
- if (msym -> constant_pool_index == 0 || msym -> constant_pool_class != class_id) { // build method ref for method
- if (is_interface) {
- msym -> constant_pool_index = BuildInterfaceMethodref(
- RegisterClass(msym -> containing_type -> fully_qualified_name),
- BuildNameAndType(
- RegisterUtf8(msym -> ExternalIdentity() -> Utf8_literal),
- RegisterUtf8(msym -> signature)));
- msym -> constant_pool_class = class_id;
- }
- else {
-
- msym -> constant_pool_index = BuildMethodref(
- RegisterClass(msym -> containing_type -> fully_qualified_name),
- BuildNameAndType(
- RegisterUtf8(msym -> ExternalIdentity() -> Utf8_literal),
- RegisterUtf8(msym -> signature)));
- msym -> constant_pool_class = class_id;
- }
- }
-
- PutU2(msym -> constant_pool_index);
- if (is_interface) {
- PutU1(stack_words+1);
- PutU1(0);
- }
- // must account for value returned by method. Assume it places one
- // word on stack and correct this assumption if wrong.
- stack_words=1;
- if (this_control.IsDoubleWordType(res_type)) {
- stack_words = 2;
- }
- else if (res_type == this_control.void_type) { // no return value
- stack_words = 0;
- }
- ChangeStack(stack_words);
- }
-
- void ByteCode::EmitNewArray(int dims,TypeSymbol * type)
- {
- int i;
- TypeSymbol * element_type = type -> ArraySubtype();
-
- if (dims==0 || (dims == 1 && type -> num_dimensions == dims)) {
- if (this_control.IsNumeric(element_type) || element_type == this_control.boolean_type) {
- // if one-dimensional primitive
- if (element_type == this_control.boolean_type) i = 4; // T_BOOLEAN
- else if (element_type == this_control.char_type) i = 5; // T_CHAR
- else if (element_type == this_control.float_type) i = 6; // T_FLOAT
- else if (element_type == this_control.double_type) i = 7;// T_DOUBLE
- else if (element_type == this_control.byte_type) i = 8; // T_BYTE
- else if (element_type == this_control.short_type) i = 9;// T_SHORT
- else if (element_type == this_control.int_type) i = 10; // T_INT
- else if (element_type == this_control.long_type) i = 11; // T_LONG
- else chaos("new array unsupported type");
- PutOp(OP_NEWARRAY);
- PutU1(i);
- return;
- }
- else {
- // must be reference type
- PutOp(OP_ANEWARRAY);
- PutU2(RegisterClass(element_type -> fully_qualified_name));
- }
- }
- else {
- PutOp(OP_MULTIANEWARRAY);
- PutU2(RegisterClass(type -> signature));
- PutU1(dims); // load dims count
- ChangeStack(dims-1); // dims -1
- }
- }
-
- int ByteCode::EmitPostUnaryExpression(AstPostUnaryExpression *expression,int need_value)
- {
- // POST_UNARY
- int kind;
- switch(kind=GetLHSKind(expression -> expression, expression -> write_method)) {
- case LHS_LOCAL:
- case LHS_STATIC:
- case LHS_STATIC_METHOD:
- EmitPostUnaryExpressionSimple(kind,expression,need_value);
- break;
- case LHS_ARRAY:
- EmitPostUnaryExpressionArray(expression, need_value);
- break;
- case LHS_FIELD:
- case LHS_CLASS_METHOD:
- EmitPostUnaryExpressionField(kind,expression,need_value);
- break;
- default:
- chaos("unknown lhs kind for assignment");
- }
- return GetTypeWords(expression-> Type());
- }
-
- void ByteCode::EmitPostUnaryExpressionField(int kind,AstPostUnaryExpression *expression,int need_value)
- {
- // AstExpression *expression;
- // POST_UNARY on instance variable
- // load value of field, duplicate, do increment or decrement, then store back, leaving original value
- // on top of stack.
- VariableSymbol * sym = (VariableSymbol *) expression -> symbol;
- TypeSymbol * type = (TypeSymbol *) sym -> owner;
- TypeSymbol * expression_type = expression-> Type();
- bool plus = (expression -> post_unary_tag == AstPostUnaryExpression::PLUSPLUS) ? true : false;
-
- if (kind==LHS_FIELD) {
- EmitFieldAccessLHS(expression -> expression);
- }
- else {
- ResolveAccess(expression -> expression, 1); // get address and value
- }
-
- if (need_value) {
- if (this_control.IsDoubleWordType(expression_type)) {
- PutOp(OP_DUP2_X1);
- }
- else PutOp(OP_DUP_X1);
- }
- if (this_control.IsSimpleIntegerValueType(expression_type)) { // TBSL: use iinc eventually
- PutOp(OP_ICONST_1);
- PutOp(plus ? OP_IADD : OP_ISUB);
- }
- else if (expression_type == this_control.long_type) {
- PutOp(OP_LCONST_1);
- PutOp(plus ? OP_LADD : OP_LSUB);
- }
- else if (expression_type == this_control.float_type) {
- PutOp(OP_FCONST_1);
- PutOp(plus ? OP_FADD : OP_FSUB);
- }
- else if (expression_type == this_control.double_type) {
- PutOp(OP_DCONST_1); // load 1.0
- PutOp(plus ? OP_DADD : OP_DSUB);
- }
- if (kind==LHS_FIELD) {
- PutOp(OP_PUTFIELD);
- ChangeStack(this_control.IsDoubleWordType(expression_type) ? -3: -2);
- PutU2(GenerateFieldReference(sym));
- }
- else {
- int stack_words = this_control.IsDoubleWordType(expression_type) ? 2: 1;
- PutOp(OP_INVOKEVIRTUAL);
- CompleteCall(expression -> write_method, stack_words, 0);
- }
- }
-
- void ByteCode::EmitPostUnaryExpressionSimple(int kind, AstPostUnaryExpression *expression, int need_value)
- {
- // AstExpression *expression;
- // POST_UNARY on local variable
- // load value of variable, duplicate, do increment or decrement, then store back, leaving original value
- // on top of stack.
- bool plus = (expression -> post_unary_tag == AstPostUnaryExpression::PLUSPLUS) ? true : false;
- TypeSymbol * expression_type = expression-> Type();
-
- if (expression_type == this_control.int_type) { // see if can use IINC
- if (IsLocal(expression)) {
- if (need_value) (void) LoadSimple(kind, expression);
- PutOp(OP_IINC);
- PutU1(expression -> symbol -> VariableCast() -> LocalVariableIndex());
- PutI1(plus ? 1 : -1);
- return;
- }
- }
- LoadSimple(kind,expression -> expression); // this will also load value needing resolution
-
- if (need_value) {
- if (this_control.IsDoubleWordType(expression_type)) {
- PutOp(OP_DUP2);
- }
- else PutOp(OP_DUP);
- }
- if (this_control.IsSimpleIntegerValueType(expression_type)) { // TBSL: use iinc eventually
- PutOp(OP_ICONST_1);
- PutOp(plus ? OP_IADD : OP_ISUB);
- EmitCast(expression_type, this_control.int_type);
- }
- else if (expression_type == this_control.long_type) {
- PutOp(OP_LCONST_1);
- PutOp(plus ? OP_LADD : OP_LSUB);
- }
- else if (expression_type == this_control.float_type) {
- PutOp(OP_FCONST_1);
- PutOp(plus ? OP_FADD : OP_FSUB);
- }
- else if (expression_type == this_control.double_type) {
- PutOp(OP_DCONST_1); // load 1.0
- PutOp(plus ? OP_DADD : OP_DSUB);
- }
- if (kind==LHS_STATIC_METHOD) {
- int stack_words = this_control.IsDoubleWordType(expression_type) ? 2: 1;
- PutOp(OP_INVOKESTATIC);
- CompleteCall(expression -> write_method, stack_words, 0);
- }
- else {
- StoreSimple(kind,expression -> expression);
- }
- }
-
-
- void ByteCode::EmitPostUnaryExpressionArrayCode(int load_op,
- int need_value,
- int dup_op,
- int const_op,
- int plus,
- int add_op,
- int sub_op,
- int store_op,
- int conv_op)
- {
- PutOp(load_op);
- if (need_value)PutOp(dup_op); // save value below saved array base and index
- PutOp(const_op);
- PutOp(plus ? add_op : sub_op);
- if (conv_op) PutOp(conv_op); // if need to convert back to desired type
- PutOp(store_op);
- }
-
- void ByteCode::EmitPostUnaryExpressionArray(AstPostUnaryExpression *expression, int need_value)
- {
- // Post Unary for which operand is array element
- // assignment for which lhs is array element
- // AstExpression *expression;
- bool plus = (expression -> post_unary_tag == AstPostUnaryExpression::PLUSPLUS) ? true : false;
- TypeSymbol * expression_type = expression-> Type();
- EmitArrayAccessLHS((AstArrayAccess *)expression -> expression); // lhs must be array access
- PutOp(OP_DUP2); // save array base and index for later store
- if (expression_type == this_control.int_type) {
- EmitPostUnaryExpressionArrayCode(OP_IALOAD, need_value, OP_DUP_X2,
- OP_ICONST_1, plus, OP_IADD, OP_ISUB, OP_IASTORE, 0);
- }
- else if (expression_type == this_control.byte_type ) {
- EmitPostUnaryExpressionArrayCode(OP_BALOAD, need_value, OP_DUP_X2,
- OP_ICONST_1, plus, OP_IADD, OP_ISUB, OP_BASTORE, OP_I2B);
- }
- else if (expression_type == this_control.char_type ) {
- EmitPostUnaryExpressionArrayCode(OP_CALOAD, need_value, OP_DUP_X2,
- OP_ICONST_1, plus, OP_IADD, OP_ISUB, OP_CASTORE, OP_I2C);
- }
- else if (expression_type == this_control.short_type) {
- EmitPostUnaryExpressionArrayCode(OP_SALOAD, need_value, OP_DUP_X2,
- OP_ICONST_1, plus, OP_IADD, OP_ISUB, OP_SASTORE, OP_I2S);
- }
- else if (expression_type == this_control.long_type) {
- EmitPostUnaryExpressionArrayCode(OP_LALOAD, need_value, OP_DUP2_X2,
- OP_LCONST_1, plus, OP_LADD, OP_LSUB, OP_LASTORE, 0);
- }
- else if (expression_type == this_control.float_type) {
- EmitPostUnaryExpressionArrayCode(OP_FALOAD, need_value, OP_DUP_X2,
- OP_FCONST_1, plus, OP_FADD, OP_FSUB, OP_FASTORE, 0);
- }
- else if (expression_type == this_control.double_type) {
- EmitPostUnaryExpressionArrayCode(OP_DALOAD, need_value, OP_DUP2_X2,
- OP_DCONST_1, plus, OP_DADD, OP_DSUB, OP_DASTORE, 0);
- }
- else chaos("unsupported postunary type");
- }
-
- int ByteCode::EmitPreUnaryExpression(AstPreUnaryExpression *expression,int need_value)
- {
- // PRE_UNARY
- TypeSymbol * type = expression-> Type();
- if (expression -> pre_unary_tag == AstPreUnaryExpression::PLUSPLUS ||
- expression -> pre_unary_tag == AstPreUnaryExpression::MINUSMINUS) {
- EmitPreUnaryIncrementExpression(expression,need_value);
- }
- else {
- // here for ordinary unary operator without side effects.
- switch (expression -> pre_unary_tag) {
- case AstPreUnaryExpression::PLUS:
- // nothing to do (front-end will have done any needed conversions)
- EmitExpression(expression -> expression);
- break;
- case AstPreUnaryExpression::MINUS:
- EmitExpression(expression -> expression);
- if (this_control.IsSimpleIntegerValueType(type)) PutOp(OP_INEG);
- else if (type == this_control.long_type) PutOp(OP_LNEG);
- else if (type == this_control.float_type) PutOp(OP_FNEG);
- else if (type == this_control.double_type) PutOp(OP_DNEG);
- else chaos("unary minus on unsupported type");
- break;
- case AstPreUnaryExpression::TWIDDLE:
- if (this_control.IsSimpleIntegerValueType(type)) {
- EmitExpression(expression -> expression);
- PutOp(OP_ICONST_M1); // -1
- PutOp(OP_IXOR); // exclusive or to get result
- }
- else if (type == this_control.long_type) {
- EmitExpression(expression -> expression);
- PutOp(OP_LCONST_1); // make -1
- PutOp(OP_LNEG);
- PutOp(OP_LXOR); // exclusive or to get result
- }
- else chaos("unary ~ on unsupported type");
- break;
- case AstPreUnaryExpression::NOT:
- if (type == this_control.boolean_type) {
- Label lab1,lab2;
- EmitExpression(expression -> expression);
- EmitBranch(OP_IFEQ,lab1);
- PutOp(OP_ICONST_0); // turn true into false
- EmitBranch(OP_GOTO,lab2);
- DefineLabel(lab1);
- PutOp(OP_ICONST_1); // here to turn false into true
- DefineLabel(lab2);
- CompleteLabel(lab1);
- CompleteLabel(lab2);
- }
- else chaos("unary ! on non-boolean not supported");
- break;
- default:
- chaos("unknown preunary tag");
- }
- }
- return GetTypeWords(type);
- // AstExpression *expression;
- }
-
- void ByteCode::EmitPreUnaryIncrementExpression(AstPreUnaryExpression *expression, int need_value)
- {
- // PRE_UNARY with side effects (++X or --X)
- int kind;
- switch(kind=GetLHSKind(expression, expression -> write_method)) {
- case LHS_LOCAL:
- case LHS_STATIC:
- case LHS_STATIC_METHOD:
- EmitPreUnaryIncrementExpressionSimple(kind,expression,need_value);
- break;
- case LHS_ARRAY:
- EmitPreUnaryIncrementExpressionArray(expression,need_value);
- break;
- case LHS_FIELD:
- case LHS_CLASS_METHOD:
- EmitPreUnaryIncrementExpressionField(kind, expression,need_value);
- break;
- default:
- chaos("unknown lhs kind for assignment");
- }
- }
-
- void ByteCode::EmitPreUnaryIncrementExpressionSimple(int kind,AstPreUnaryExpression *expression, int need_value)
- {
- // AstExpression *expression;
- // POST_UNARY on name
- // load value of variable, do increment or decrement, duplicate, then store back, leaving original value
- // on top of stack.
- bool plus = (expression -> pre_unary_tag == AstPreUnaryExpression::PLUSPLUS) ? true : false;
- TypeSymbol * type = expression-> Type();
- if (type == this_control.int_type) {
-
- if (kind == LHS_LOCAL) {
- PutOp(OP_IINC);
- PutU1(expression -> symbol -> VariableCast() -> LocalVariableIndex());
- PutI1(plus ? 1 : -1);
- if (need_value) (void) LoadSimple(kind, expression);
- return;
- }
- }
- (void) LoadSimple(kind,expression -> expression); // will also load value if resolution needed
-
- if (this_control.IsSimpleIntegerValueType(type)) { // TBSL: use iinc eventually
- PutOp(OP_ICONST_1);
- PutOp(plus ? OP_IADD : OP_ISUB);
- EmitCast(type, this_control.int_type);
- if (need_value) PutOp(OP_DUP);
- }
- else if (type == this_control.long_type) {
- PutOp(OP_LCONST_1);
- PutOp(plus ? OP_LADD : OP_LSUB);
- if (need_value) PutOp(OP_DUP2);
- }
- else if (type == this_control.float_type) {
- PutOp(OP_FCONST_1);
- PutOp(plus ? OP_FADD : OP_FSUB);
- if (need_value) PutOp(OP_DUP);
- }
- else if (type == this_control.double_type) {
- PutOp(OP_DCONST_1); // load 1.0
- PutOp(plus ? OP_DADD : OP_DSUB);
- if (need_value) PutOp(OP_DUP2);
- }
- if (kind==LHS_STATIC_METHOD) {
- int stack_words = this_control.IsDoubleWordType(type) ? 2: 1;
- PutOp(OP_INVOKESTATIC);
- CompleteCall(expression -> write_method, stack_words, 0);
- }
- else {
- StoreSimple(kind,expression);
- }
- }
-
- void ByteCode::EmitPreUnaryIncrementExpressionArrayCode(int load_op,
- int const_op,
- int plus,
- int add_op,
- int sub_op,
- int need_value,
- int dup_op,
- int store_op,
- int conv_op)
- {
- PutOp(load_op);
- PutOp(const_op);
- PutOp(plus ? add_op : sub_op);
- if (need_value) PutOp(dup_op); // save value below saved array base and index
- if (conv_op) PutOp(conv_op); // if need to check result in range
- PutOp(store_op);
- }
-
- void ByteCode::EmitPreUnaryIncrementExpressionArray(AstPreUnaryExpression *expression, int need_value)
- {
- // Post Unary for which operand is array element
- // assignment for which lhs is array element
- // AstExpression *expression;
- bool plus = (expression -> pre_unary_tag == AstPreUnaryExpression::PLUSPLUS) ? true : false;
- TypeSymbol * type = expression-> Type();
- EmitArrayAccessLHS((AstArrayAccess *)expression -> expression); // lhs must be array access
- PutOp(OP_DUP2); // save array base and index for later store
- if (type == this_control.int_type) {
- EmitPreUnaryIncrementExpressionArrayCode(OP_IALOAD, OP_ICONST_1,
- plus, OP_IADD, OP_ISUB, need_value, OP_DUP_X2, OP_IASTORE,0);
- }
- else if (type == this_control.byte_type) {
- EmitPreUnaryIncrementExpressionArrayCode(OP_BALOAD, OP_ICONST_1,
- plus, OP_IADD, OP_ISUB, need_value, OP_DUP_X2, OP_BASTORE, OP_I2B);
- }
- else if (type == this_control.char_type) {
- EmitPreUnaryIncrementExpressionArrayCode(OP_CALOAD, OP_ICONST_1,
- plus, OP_IADD, OP_ISUB, need_value, OP_DUP_X2, OP_CASTORE, OP_I2C);
- }
- else if (type == this_control.short_type) {
- EmitPreUnaryIncrementExpressionArrayCode(OP_SALOAD, OP_ICONST_1,
- plus, OP_IADD, OP_ISUB, need_value, OP_DUP_X2, OP_SASTORE, OP_I2S);
- }
- else if (type == this_control.long_type) {
- EmitPreUnaryIncrementExpressionArrayCode(OP_LALOAD, OP_LCONST_1,
- plus, OP_LADD, OP_LSUB, need_value, OP_DUP2_X2, OP_LASTORE, 0);
- }
- else if (type == this_control.float_type) {
- EmitPreUnaryIncrementExpressionArrayCode(OP_FALOAD, OP_FCONST_1,
- plus, OP_FADD, OP_FSUB, need_value, OP_DUP_X2, OP_FASTORE, 0);
- }
- else if (type == this_control.double_type) {
- EmitPreUnaryIncrementExpressionArrayCode(OP_DALOAD, OP_DCONST_1,
- plus, OP_DADD, OP_DSUB, need_value, OP_DUP2_X2, OP_DASTORE, 0);
- }
- else chaos("unsupported PreUnary type");
- }
-
- void ByteCode::EmitPreUnaryIncrementExpressionField(int kind, AstPreUnaryExpression *expression, int need_value)
- {
- // Pre Unary for which operand is field (instance variable)
- // AstExpression *expression;
- bool plus = (expression -> pre_unary_tag == AstPreUnaryExpression::PLUSPLUS) ? true : false;
- VariableSymbol * sym = (VariableSymbol *) expression -> symbol;
- TypeSymbol * type = (TypeSymbol *) sym -> owner;
- TypeSymbol * expression_type = expression-> Type();
- if (kind==LHS_CLASS_METHOD) {
- // need to load address of object, obtained from resolution, saving a copy on the stack
- ResolveAccess(expression -> expression, 1); // get address and value
- }
- else {
- EmitFieldAccessLHS(expression -> expression);
- }
- if (this_control.IsSimpleIntegerValueType(expression_type)) {
- PutOp(OP_ICONST_1);
- PutOp(plus ? OP_IADD : OP_ISUB);
- EmitCast(expression_type, this_control.int_type);
- if (need_value)PutOp(OP_DUP_X1);
- }
- else if (expression_type == this_control.long_type) {
- PutOp(OP_LCONST_1);
- PutOp(plus ? OP_LADD : OP_LSUB);
- if (need_value)PutOp(OP_DUP2_X1);
- }
- else if (expression_type == this_control.float_type) {
- PutOp(OP_FCONST_1);
- PutOp(plus ? OP_FADD : OP_FSUB);
- if (need_value)PutOp(OP_DUP_X1);
- }
- else if (expression_type == this_control.double_type) {
- PutOp(OP_DCONST_1);
- PutOp(plus ? OP_DADD : OP_DSUB);
- if (need_value)PutOp(OP_DUP2_X1);
- }
- else chaos("unsupported PreUnary type");
- if (kind==LHS_CLASS_METHOD) {
- int stack_words = this_control.IsDoubleWordType(expression_type) ? 2: 1;
- PutOp(OP_INVOKEVIRTUAL);
- CompleteCall(expression -> write_method, stack_words, 0);
- }
- else {
- PutOp(OP_PUTFIELD);
- ChangeStack(this_control.IsDoubleWordType(expression_type) ? -3: -2);
- PutU2(GenerateFieldReference(sym));
- }
- }
-
- void ByteCode::EmitThisInvocation(AstThisCall *this_call)
- {
- MethodSymbol * msym = this_call -> symbol;
- AstExpression *base_opt = this_call -> base_opt;
-
- // THIS_CALL
- // AstExpression *method;
- // AstList *arguments;
- // A call to another constructor (THIS_CALL) or super constructor (SUPER_CALL)
- // result in the same sort of generated code, as the semantic analysis
- // has resolved the proper constructor to be invoked.
- int stack_words = 0; // words on stack needed for arguments
- PutOp(OP_ALOAD_0); // load 'this'
- if (base_opt) {
- stack_words += EmitExpression(base_opt);
- }
- for (int i=0; i < this_call -> NumLocalArguments();i++) {
- stack_words += EmitExpression((AstExpression *) this_call -> LocalArgument(i));
- }
- for (int k=0; k < this_call -> NumArguments();k++) {
- stack_words += EmitExpression((AstExpression *) this_call -> Argument(k));
- }
- PutOp(OP_INVOKENONVIRTUAL);
- ChangeStack(-stack_words);
- // need to get method index, the constant_pool index for a
- // reference to this method (a Methodref);
- // caller will supply methodref
- if (msym -> constant_pool_index == 0 || msym -> constant_pool_class != class_id) { // build method ref for method
- msym -> constant_pool_index = BuildMethodref(
- this_class,
- BuildNameAndType(
- RegisterUtf8(msym -> ExternalIdentity() -> Utf8_literal),
- RegisterUtf8(msym -> signature)));
- msym -> constant_pool_class = class_id;
-
- }
-
- PutU2(msym -> constant_pool_index);
- }
-
-
- void ByteCode::EmitSuperInvocation(AstSuperCall *super_call)
- {
- MethodSymbol *msym = super_call -> symbol;
- AstExpression *base_opt = super_call -> base_opt;
-
- int stack_words = 0; // words on stack needed for arguments
- PutOp(OP_ALOAD_0); // load 'this'
- if (base_opt) {
- stack_words += EmitExpression(base_opt);
- }
- for (int i=0; i < super_call -> NumLocalArguments();i++) {
- stack_words += EmitExpression((AstExpression *) super_call -> LocalArgument(i));
- }
- for (int k=0; k < super_call -> NumArguments();k++) {
- stack_words += EmitExpression((AstExpression *) super_call -> Argument(k));
- }
- PutOp(OP_INVOKENONVIRTUAL);
- ChangeStack(-stack_words);
- // need to get method index, the constant_pool index for a
- // reference to this method (a methodref);
- // caller will supply methodref
- if (msym -> constant_pool_index == 0 || msym -> constant_pool_class != class_id) { // build method ref for method
- msym -> constant_pool_index = BuildMethodref(
- super_class,
- BuildNameAndType(
- RegisterUtf8(msym -> ExternalIdentity() -> Utf8_literal),
- RegisterUtf8(msym -> signature)));
- msym -> constant_pool_class = class_id;
-
- }
-
- PutU2(msym -> constant_pool_index);
- }
-
-
- AstExpression * ByteCode::UnParenthesize(AstExpression * p)
- {
- // called when expression has been parenthesized to removed
- // parantheses and expose true structure.
- AstParenthesizedExpression * pe;
- while (p -> ParenthesizedExpressionCast()) {
- p = p -> ParenthesizedExpressionCast() -> expression;
- }
- return p;
- }
-
- // Methods for string concatenation
-
- void ByteCode::ConcatenateString(AstBinaryExpression * expression)
- {
- // generate code to concatenate strings, by generating a string buffer and appending the arguments
- // before calling toString, i.e.,
- // s1+s2 compiles to
- // new StringBuffer().append(s1).append(s2).toString();
- // look for sequences of concatenation to use a single buffer where possible
- EmitStringBuffer();
- AppendString(expression -> left_expression);
- AppendString(expression -> right_expression);
- EmitCallStringToString(); // convert string buffer to string
- }
-
- void ByteCode::EmitCallStringToString()
- { // generate call to toString on stringbuffer
- PutOp(OP_INVOKEVIRTUAL);
- PutU2(RegisterMethod(METHOD_STRINGBUFFER_TOSTRING));
- ChangeStack(1); // account for return value
- }
- void ByteCode::EmitStringBuffer()
- {
- // generate code to allocate new string buffer and initialize it
- PutOp(OP_NEW);
- PutU2(RegisterClass(U8S_java_SL_lang_SL_StringBuffer, strlen(U8S_java_SL_lang_SL_StringBuffer)));
- PutOp(OP_DUP);
- PutOp(OP_INVOKENONVIRTUAL);
- PutU2(RegisterMethod(METHOD_STRINGBUFFER_INIT));
- }
-
- void ByteCode::AppendString(AstExpression * p)
- {
- AstBinaryExpression *binexpr;
- TypeSymbol * type = p-> Type();
- if (p -> BinaryExpressionCast()) {
- binexpr = p -> BinaryExpressionCast();
- if ( binexpr -> binary_tag == AstBinaryExpression::PLUS
- && (IsReferenceType(binexpr -> left_expression-> Type()) ||
- IsReferenceType(binexpr -> right_expression-> Type()))) {
- AppendString(binexpr -> left_expression);
- AppendString(binexpr -> right_expression);
- return;
- }
- }
- if (p -> ParenthesizedExpressionCast()) {
- AppendString(p -> ParenthesizedExpressionCast() -> expression);
- return;
- }
- if (p -> CastExpressionCast()) { // here if cast expression, verify that converting to string
- AstCastExpression *cast = (AstCastExpression *) p;
- if (cast->kind == Ast::CAST && cast-> Type() == this_control.String()) {
- AppendString(cast->expression);
- return;
- }
- }
- if (type == this_control.null_type) {
- // replace explicit reference to "null" by
- // corresponding string.
- name_StringNull = BuildString(RegisterUtf8(U8S_null, strlen(U8S_null)));
- if (name_StringNull <=255) {
- PutOp(OP_LDC);
- PutU1((unsigned char) name_StringNull);
- }
- else {
- PutOp(OP_LDC_W);
- PutU2(name_StringNull);
- }
- type = this_control.String();
- }
- else {
- EmitExpression(p);
- }
- EmitStringAppendMethod(type);
- }
-
- void ByteCode::EmitStringAppendMethod(TypeSymbol * type)
- {
- int method_sig = 0;
- int stack_words = 1; // assume one word put on stack
- // call appropriate append routine to add to string buffer
- if (type -> num_dimensions == 1 && type -> base_type == this_control.char_type) {
- method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDCHARARRAY);
- }
- else if (type == this_control.char_type) {
- method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDCHAR);
- }
- else if (type == this_control.boolean_type) {
- method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDBOOLEAN);
- }
- else if (type == this_control.int_type|| type == this_control.short_type || type == this_control.byte_type) {
- method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDINT);
- }
- else if (type == this_control.long_type) {
- method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDLONG);
- stack_words++;
- }
- else if (type == this_control.float_type) {
- method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDFLOAT);
- }
- else if (type == this_control.double_type) {
- method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDDOUBLE);
- stack_words++;
- }
- else if (type == this_control.String()) {
- method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDSTRING);
- }
- else if (IsReferenceType(type)) {
- // may need to call toString method on object before appending to stringbuffer
- // TODO: do above
- method_sig = RegisterMethod(METHOD_STRINGBUFFER_APPENDOBJECT);
- }
- else {
- chaos("unexpected string buffer append operand");
- }
- PutOp(OP_INVOKEVIRTUAL);
- ChangeStack(-stack_words);
- PutU2(method_sig);
- ChangeStack(1); // account for return value
- if (method_sig == 0) chaos("unable to find type for string buffer concatenation");
- }
- void ByteCode::chaos(char *msg) {
- cout << "chaos: " << msg << "\n";
- cerr << "chaos: " << msg << "\n";
- exit(1);
- }
- #ifdef TEST
- static void op_trap()
- {
- int i=0;
- // used for debugger trap
- }
- #endif
-
- ByteCode::ByteCode(TypeSymbol *unit_type) : ClassFile(unit_type),
- this_semantic(*unit_type -> semantic_environment -> sem),
- this_control(unit_type -> semantic_environment -> sem -> control)
- {
- int i;
-
- #ifdef TEST
- if (this_control.option.nowrite == 0) {
- this_control.class_files_written++;
- }
- #endif
- this_control.class_file_id++;
- class_id = this_control.class_file_id;
- initialize_statics_in_clinit = 1;
- stack_depth = 0;
- synchronized_blocks = 0;
- finally_blocks = 0;
-
- for (i=0;i<METHOD_NUMBER;i++) registered_methods[i] = 0;
- name_StringNull=0;
-
- access_flags = unit_type -> access_flags;
- // The flags for 'static' and 'protected' are set only for the inner
- // classes attribute, not for the class, as described in page 25
- // of the inner classes document.
- if (unit_type -> ACC_PROTECTED()) {
- access_flags |= 0x0001; // set PUBLIC if PROTECTED
- }
- access_flags &= (~ 0x0008); // ResetACC_STATIC
- access_flags &= (~ 0x0004); // ResetACC_PROTECTED
- access_flags &= (~ 0x0002); // ResetACC_PRIVATE
-
- access_flags |= 0x0020; // must be set always set ACC_SUPER for class (cf page 86 of JVM Spec)
-
- magic = 0xcafebabe;
- major_version = 45; // use Sun JDK 1.0 version numbers
- minor_version = 3;
- constant_pool.Next()=NULL;
- this_class = RegisterClass(unit_type -> fully_qualified_name);
-
- if (unit_type -> super) {
- super_class = RegisterClass(unit_type -> super -> fully_qualified_name);
- }
- else {
- super_class=0; // primordial beast Object
- }
-
- for (i=0; i<unit_type -> NumInterfaces();i++) {
- interfaces.Next() = RegisterClass(unit_type -> Interface(i) -> fully_qualified_name);
- }
-
- return;
- }
-
-
- // Methods for manipulating labels
-
- void ByteCode::DefineLabel(Label& lab)
- {
- if (lab.defined){
- chaos( "duplicate label definition");
- }
- lab.defined = 1;
- lab.definition = code_attribute -> code.Length();
- if (lab.definition > last_label_pc) {
- last_label_pc = lab.definition;
- }
- }
- void ByteCode::CompleteLabel(Label& lab)
- {
- // patch all uses to have proper value. This requires that
- // all labels be freed at some time.
- if (lab.uses.Length()) {
- if (lab.defined == 0) {
- chaos("label used but with no definition");
- }
- for (int i=0; i<lab.uses.Length();i++) {
- // patch byte code reference to label to reflect it's definition
- // as 16-bit signed offset.
- unsigned int luse = lab.uses[i].use_offset;;
- int start = luse - lab.uses[i].op_offset;
- int offset = lab.definition - start;
- if (lab.uses[i].use_length == 2) {
- // here if short offset
- code_attribute -> code[luse] = (offset >> 8) & 0xFF;
- code_attribute -> code[luse+1] = offset & 0xFF;
- }
- else if (lab.uses[i].use_length == 4) {
- //here if 4 byte use
- code_attribute -> code[luse] = (offset >> 24) & 0xFF;
- code_attribute -> code[luse+1] = (offset >> 16) & 0xFF;
- code_attribute -> code[luse+2] = (offset >> 8) & 0xFF;
- code_attribute -> code[luse+3] = offset & 0xFF;
- }
- else {
- chaos( "label use length not 2 or 4");
- exit(1);
- }
-
- }
- lab.uses.Reset();
- }
- // reset in case label is used again.
- lab.definition = 0;
- lab.defined=0;
- }
-
-
- int ByteCode::IsLabelUsed(Label& lab)
- {
- return (lab.uses.Length()>0);
- }
-
- // int ByteCode::IsLabelDefined(Label& lab)
- // {
- // return (lab.defined != 0);
- // }
-
- void ByteCode::UseLabel(Label & lab,int _length, int _op_offset)
- {
- int lab_index = lab.uses.NextIndex();
- lab.uses[lab_index].use_length = _length;
- lab.uses[lab_index].op_offset = _op_offset;
- lab.uses[lab_index].use_offset = code_attribute -> code.Length();
-
- // fill next length bytes with zero; will be filled in with proper value when label completed
- for (int i=0;i<lab.uses[lab_index].use_length;i++) code_attribute -> code.Next() = 0;
- }
-
- // Methods to query attributes
-
- int ByteCode::IsLocal(AstExpression *p)
- {
- // return 1 if p refers to local variable, 0 otherwise
- VariableSymbol *sym = p -> symbol -> VariableCast();
- return (sym && sym -> owner -> MethodCast()) ? 1 : 0;
- }
-
- int ByteCode::IsNull(AstExpression *p)
- {
- // see if operand is null. The front-end will have inserted a cast
- // of null to the present type
- if (p -> CastExpressionCast()) {
- return p -> CastExpressionCast() -> expression-> Type() == this_control.null_type;
- }
- else return 0;
- }
-
- int ByteCode::IsReferenceType(TypeSymbol *p)
- {
- return (! (this_control.IsNumeric(p)
- || p == this_control.boolean_type || p == this_control.null_type));
- }
-
-
- int ByteCode::IsDefaultValue(AstExpression *p)
- {
- // see if operand is default value of its type
- TypeSymbol *type = p-> Type();
- if (!p -> IsConstant()) return 0;
- LiteralValue * litp = p -> value;
- if (this_control.IsSimpleIntegerValueType(type) || type == this_control.boolean_type) {
- IntLiteralValue * vp = (IntLiteralValue *) litp;
- int val = vp -> value;
- return (val == 0);
- }
- else if (type == this_control.long_type) {
- LongLiteralValue * vp = (LongLiteralValue *) litp;
- LongInt val = vp -> value;
- return (val == 0);
- }
- else if (type == this_control.float_type) {
- FloatLiteralValue * vp = (FloatLiteralValue *) litp;
- IEEEfloat val = vp -> value;
- return (val.Word() == 0);
- }
-
- else if (type == this_control.double_type) {
- DoubleLiteralValue * vp = (DoubleLiteralValue *) litp;
- IEEEdouble val = vp -> value;
- return (val.HighWord() == 0 && val.LowWord() == 0);
- }
- else {
- // the default value for everything else is 'null'
- return (type == this_control.null_type);
- }
-
- return 0;
- }
-
- int ByteCode::IsZero(AstExpression *p)
- {
- // see if operand is integer type and is zero
- TypeSymbol *type = p-> Type();
- if (!p -> IsConstant()) return 0;
- if (p-> Type() == this_control.int_type||p-> Type() == this_control.boolean_type) {
- LiteralValue * litp = p -> value;
- IntLiteralValue * vp = (IntLiteralValue *) litp;
- int val = vp -> value;
- return (val == 0);
- }
- return 0;
- }
- int ByteCode::GetTypeWords(TypeSymbol * type)
- {
- return this_control.IsDoubleWordType(type) ? 2: 1;
- }
-
- int ByteCode::GetLHSKind(AstExpression * expression, MethodSymbol * msym)
- {
- if (msym) { // if has write_method
- if (msym -> ACC_STATIC())
- return LHS_STATIC_METHOD;
- else
- return LHS_CLASS_METHOD;
- }
-
- if (expression -> CastExpressionCast()) {
- expression = expression -> CastExpressionCast() -> expression;
- }
- else if (expression -> PreUnaryExpressionCast()) {
- expression = expression -> PreUnaryExpressionCast() -> expression;
- }
- else if (expression -> PostUnaryExpressionCast()) {
- expression = expression -> PostUnaryExpressionCast() -> expression;
- }
-
- //
- // A left-hand side is either an array access,
- // a field access or a name. In the case of a FieldAccess
- // or name, the left-hand side is resolved into a variable.
- // In the case of an array access, it is resolved into a type.
- //
- VariableSymbol * sym = expression -> symbol -> VariableCast();
- if (! sym) return LHS_ARRAY;
- else if (sym -> owner -> MethodCast()) return LHS_LOCAL;
- else if (sym -> ACC_STATIC()) return LHS_STATIC;
- else return LHS_FIELD;
- }
-
- // Methods to load values
- int ByteCode::GetConstant(LiteralValue *litp, TypeSymbol *type)
- {
- int lit_index;
-
- if (type == this_control.String()) {
- Utf8LiteralValue *vp = (Utf8LiteralValue *) litp;
- if (vp -> constant_pool_index_String != 0 && vp -> constant_pool_class == class_id)
- lit_index = vp -> constant_pool_index_String;
- else {
- // must be string
- lit_index = RegisterString(vp);
- }
- }
- else {
- if (litp -> constant_pool_index != 0 && litp -> constant_pool_class == class_id)
- lit_index = litp -> constant_pool_index;
- else {
- // load literal using literal value
- if (this_control.IsSimpleIntegerValueType(type) || type == this_control.boolean_type) {
- IntLiteralValue * vp = (IntLiteralValue *) litp;
- lit_index = RegisterInteger(vp);
- }
- else if (type == this_control.float_type) {
- FloatLiteralValue * vp = (FloatLiteralValue *) litp;
- IEEEfloat val = vp -> value;
- lit_index = RegisterFloat(vp);
- }
- else if (type == this_control.long_type) {
- LongLiteralValue * vp = (LongLiteralValue *) litp;
- lit_index = RegisterLong(vp);
- }
- else if (type == this_control.double_type) {
- DoubleLiteralValue * vp = (DoubleLiteralValue *) litp;
- lit_index = RegisterDouble(vp);
- }
- else chaos("unexpected GetConstant kind");
- }
- }
-
- return lit_index;
- }
-
- int ByteCode::LoadConstant(AstExpression *p)
- {
- // here to load a constant when the LiteralValue is set.
-
- LiteralValue * litp = p -> value;
- if (!p -> IsConstant()) {
- chaos("constant expected by LoadConstant");
- }
- return LoadLiteral(p -> value,p-> Type());
- }
-
-
- int ByteCode::LoadLiteral(LiteralValue* litp, TypeSymbol *type)
- {
- // int lit_index = litp -> constant_pool_index;
- int lit_index;
- int is_long_or_double=0; // set if need lcd2_w
- if (litp -> constant_pool_index >0 && litp -> constant_pool_class == class_id) lit_index= litp -> constant_pool_index;
- else lit_index = 0;
- // see if can load without using LDC even if have literal index; otherwise generate constant pool entry
- // if one has not yet been generated.
- if (litp == this_control.NullValue()) {
- PutOp(OP_ACONST_NULL);
- return 1;
- }
- if (type == this_control.String()) {
- // register index as string if this has not yet been done
- Utf8LiteralValue * lv = (Utf8LiteralValue *) litp;
- lit_index = RegisterString(lv);
- }
- // load literal using literal value
- // note that boolean literal values stored as int literals
- else if (this_control.IsSimpleIntegerValueType(type) || type == this_control.boolean_type) {
- IntLiteralValue * vp = (IntLiteralValue *) litp;
- int val = vp -> value;
- if (val >= -32768 && val <32768) {
- LoadShort(val);
- return 1;
- }
- lit_index = RegisterInteger(vp);
- }
- else if (type == this_control.float_type) {
- FloatLiteralValue * vp = (FloatLiteralValue *) litp;
- IEEEfloat val = vp -> value;
- if (val.Word() == 0) { // if float 0.0
- PutOp(OP_FCONST_0);
- return 1;
- }
- else if (val.Word() == 0x3f800000) { // if float 1.0
- PutOp(OP_FCONST_1);
- return 1;
- }
- else if (val.Word() == 0x40000000) { // if float 2.0
- PutOp(OP_FCONST_2);
- return 1;
- }
- lit_index = RegisterFloat(vp);
- }
- else if (type == this_control.long_type) {
- LongLiteralValue * vp = (LongLiteralValue *) litp;
- LongInt val = vp -> value;
- if (val == 0) {
- PutOp(OP_LCONST_0); // long 0
- return 2;
- }
- else if (val == 1) {
- PutOp(OP_LCONST_1); // long 1
- return 2;
- }
- lit_index = RegisterLong(vp);
- is_long_or_double=1;
- }
- else if (type == this_control.double_type) {
- //
- DoubleLiteralValue * vp = (DoubleLiteralValue *) litp;
- IEEEdouble val = vp -> value;
- if(val.HighWord() == 0 && val.LowWord() == 0) {
- PutOp(OP_DCONST_0);
- return 2;
- }
- else if (val.HighWord() == 0x3ff00000 && val.LowWord() == 0x00000000) { // if double 1.0
- PutOp(OP_DCONST_1);
- return 2;
- }
- else { // if need ldc2_w
- lit_index = RegisterDouble(vp);
- is_long_or_double=1;
- }
- }
- else {
- chaos("unsupported constant kind");
- }
- if (lit_index == 0) chaos("lit_index zero");
- if(!is_long_or_double && lit_index <=255) {
- PutOp(OP_LDC);
- PutU1(lit_index);
- }
- else {
- PutOp(is_long_or_double ? OP_LDC2_W : OP_LDC_W);
- PutU2(lit_index);
- }
- return is_long_or_double + 1;
- }
- void ByteCode::LoadLocalVariable(VariableSymbol * var)
- {
- LoadLocal(var -> LocalVariableIndex(), var-> Type());
- }
- void ByteCode::LoadLocal(int varno, TypeSymbol * type)
- {
- int opc0, opc;
- if (this_control.IsSimpleIntegerValueType(type)|| type == this_control.boolean_type) {
- opc0 = OP_ILOAD_0; opc = OP_ILOAD;
- }
- else if (type == this_control.long_type) {
- opc0 = OP_LLOAD_0; opc = OP_LLOAD;
- }
- else if (type == this_control.float_type) {
- opc0 = OP_FLOAD_0; opc = OP_FLOAD;
- }
- else if (type == this_control.double_type) {
- opc0 = OP_DLOAD_0; opc = OP_DLOAD;
- }
- else { // assume reference
- opc0 = OP_ALOAD_0; opc = OP_ALOAD;
- }
- if (varno<=3) PutOp(opc0+varno);
- else if (varno<256) {
- PutOp(opc); PutU1(varno);
- }
- else {
- PutOp(OP_WIDE); PutOp(opc); PutU2(varno);
- }
- }
- void ByteCode::LoadInteger(int val)
- {
-
- if (val >= -32768 && val <32768) { // if short
- LoadShort(val);
- }
- else {
- u2 index = BuildInteger(val);
- if (index <=255) {
- PutOp(OP_LDC);
- PutU1((unsigned char) index);
- }
- else {
- PutOp(OP_LDC_W);
- PutU2(index);
- }
- }
- }
-
- void ByteCode::LoadShort(int val)
- { // load short (signed) value onto stack
- if (val >= -128 && val <128) {
- switch (val) {
- case -1:
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- PutOp(OP_ICONST_0 + val); // exploit opcode encoding
- break;
- default: // else put byte value
- PutOp(OP_BIPUSH);
- PutU1(val);
- }
- }
- else if (val >= -32768 && val <32768) { // if short
- PutOp(OP_SIPUSH);
- PutU1((val >> 8));
- PutU1(val);
- }
- else {
- chaos("bcShort operand not short!");
- }
- }
- void ByteCode::ResolveAccess(AstExpression *p, int need_value)
- {
- // if need_value zero, then just get address for access of private member
- // else get value with an extra copy of the needed address below the value
- AstExpression * resolve;
- if (p -> FieldAccessCast()) {
- resolve = p -> FieldAccessCast() -> resolution_opt;
- }
- else if (p -> SimpleNameCast()) {
- resolve = p -> SimpleNameCast() -> resolution_opt;
- }
- if (resolve -> MethodInvocationCast()) {
- if (need_value) {
- EmitMethodInvocation(resolve -> MethodInvocationCast(), 1);
- }
- else {
- // next does too much, getting base and field value; just want base
- //Expression(resolve -> MethodInvocationCast() -> method);
- if (resolve -> MethodInvocationCast() -> method -> FieldAccessCast()) {
- AstFieldAccess * field_expression =
- resolve -> MethodInvocationCast() -> method -> FieldAccessCast();
- // VariableSymbol * sym = (VariableSymbol *) field_expression -> owner;
- EmitExpression (field_expression -> base);
- }
- else {
- chaos("field access expected in method resolution");
- }
- }
- }
- else {
- chaos("method invocation expected here");
- }
- }
-
- int ByteCode::LoadSimple (int kind,AstExpression *p)
- {
- VariableSymbol * sym = (VariableSymbol *) p -> symbol;
- TypeSymbol * type = (TypeSymbol *) sym -> owner;
- TypeSymbol * expression_type = p-> Type();
- switch (kind) {
- case LHS_LOCAL:
- LoadLocal(sym -> LocalVariableIndex(), expression_type);
- break;
- case LHS_STATIC_METHOD:
- EmitExpression(p); // will do resolution
- break;
- case LHS_FIELD:
- case LHS_STATIC:
- {
- if (sym -> ACC_STATIC()) {
- PutOp(OP_GETSTATIC);
- ChangeStack(GetTypeWords(expression_type));
- }
- else {
- PutOp(OP_ALOAD_0); // get address of "this"
- PutOp(OP_GETFIELD);
- ChangeStack(GetTypeWords(expression_type)-1);
- }
- PutU2(GenerateFieldReference(sym));
- break;
- }
- default: chaos("LoadSimple bad kind");
- }
- return GetTypeWords(expression_type);
- }
-
- void ByteCode::LoadReference(AstExpression *expression)
- {
- //load reference from local variable.
- // otherwise will use getstatic or getfield.
- TypeSymbol * type;
- int is_local=0,varno;
- if (expression -> ParenthesizedExpressionCast()) {
- expression = UnParenthesize(expression);
- }
- VariableSymbol * sym = expression -> symbol -> VariableCast();
- if (sym && sym -> owner -> MethodCast()) {
- is_local=1;
- varno = sym -> LocalVariableIndex();
- LoadLocal(varno,expression-> Type());
- return;
- }
- if (expression -> ArrayAccessCast()) { // nested array reference
- EmitArrayAccessLHS(expression -> ArrayAccessCast());
- PutOp(OP_AALOAD);
- }
- else if (expression -> FieldAccessCast() && expression -> FieldAccessCast() -> resolution_opt) {
- EmitExpression(expression -> FieldAccessCast() -> resolution_opt);
- return;
- }
- else if (expression -> FieldAccessCast() && (type=sym -> owner -> TypeCast())) {
- // TypeSymbol * expression_type = expression-> Type();
- // here if field
- if (sym -> ACC_STATIC()) {
- PutOp(OP_GETSTATIC);
- ChangeStack(this_control.IsDoubleWordType(type) ? 2: 1);
- }
- else {
- AstFieldAccess *field = expression -> FieldAccessCast();
- if (field){
- EmitExpression(field -> base);
- }
- else if (expression -> SimpleNameCast()) {
- PutOp(OP_ALOAD_0); // get address of "this"
- }
- else {
- chaos("LoadReference unexpected base type");
- }
- PutOp(OP_GETFIELD);
- ChangeStack(this_control.IsDoubleWordType(type) ? 1: 0);
- }
- PutU2(GenerateFieldReference(sym));
- }
- else { // must have expression, the value of which is reference
- EmitExpression(expression);
- }
- }
-
- int ByteCode::LoadArrayElement(TypeSymbol * type)
- {
- int opc;
- if (type == this_control.byte_type
- || type == this_control.boolean_type) opc=OP_BALOAD;
- else if (type == this_control.short_type) opc = OP_SALOAD;
- else if (type == this_control.int_type) opc = OP_IALOAD;
- else if (type == this_control.long_type) opc = OP_LALOAD;
- else if (type == this_control.char_type) opc = OP_CALOAD;
- else if (type == this_control.float_type) opc = OP_FALOAD;
- else if (type == this_control.double_type) opc = OP_DALOAD;
- else opc = OP_AALOAD; // assume reference
- PutOp(opc);
- return GetTypeWords(type);
- }
-
- void ByteCode::StoreArrayElement(TypeSymbol * type)
- {
- int opc;
- if (type == this_control.byte_type
- || type == this_control.boolean_type) opc=OP_BASTORE;
- else if (type == this_control.short_type) opc = OP_SASTORE;
- else if (type == this_control.int_type) opc = OP_IASTORE;
- else if (type == this_control.long_type) opc = OP_LASTORE;
- else if (type == this_control.char_type) opc = OP_CASTORE;
- else if (type == this_control.float_type) opc = OP_FASTORE;
- else if (type == this_control.double_type) opc = OP_DASTORE;
- else opc = OP_AASTORE; // assume reference
- PutOp(opc);
- }
-
-
- // Method to generate field reference
- void ByteCode::StoreField(AstExpression *expression)
- {
- // DOT
- VariableSymbol * sym = (VariableSymbol *) expression -> symbol;
- TypeSymbol * type = (TypeSymbol *) sym -> owner;
- TypeSymbol * expression_type=expression-> Type();
- if (sym -> ACC_STATIC()) {
- PutOp(OP_PUTSTATIC);
- ChangeStack(this_control.IsDoubleWordType(expression_type) ? -2: -1);
- }
- else {
- PutOp(OP_PUTFIELD);
- ChangeStack(this_control.IsDoubleWordType(expression_type) ? -3: -2);
- }
- PutU2(GenerateFieldReference(sym));
- }
-
- void ByteCode::StoreLocalVariable(VariableSymbol * var)
- {
- StoreLocal(var -> LocalVariableIndex(), var-> Type());
- if (this_control.option.g && var -> LocalVariableIndex() > last_parameter_index) {
- if (var -> local_program_counter == 0) {
- // here to update point of first assignment, marking point at which value is
- // available to be displayed by debugger.
- var -> local_program_counter = code_attribute -> code.Length();
- }
- }
- }
-
- void ByteCode::StoreLocal(int varno, TypeSymbol * type)
- {
- int opc0, opc;
- if (this_control.IsSimpleIntegerValueType(type)|| type == this_control.boolean_type) {
- opc0 = OP_ISTORE_0; opc = OP_ISTORE;
- }
- else if (type == this_control.long_type) {
- opc0 = OP_LSTORE_0; opc = OP_LSTORE;
- }
- else if (type == this_control.float_type) {
- opc0 = OP_FSTORE_0; opc = OP_FSTORE;
- }
- else if (type == this_control.double_type) {
- opc0 = OP_DSTORE_0; opc = OP_DSTORE;
- }
- else { // assume reference
- opc0 = OP_ASTORE_0; opc = OP_ASTORE;
- }
- if (varno<=3) PutOp(opc0+varno);
- else if (varno<256) {
- PutOp(opc); PutU1(varno);
- }
- else {
- PutOp(OP_WIDE); PutOp(opc); PutU2(varno);
- }
- }
-
-
- int ByteCode::GenerateFieldReference(VariableSymbol * sym)
- {
- // generate a field reg from symbol and class literal
- // build field ref for field
- // the field ref requires Utf8 entries for the containing
- // class, the field name and the field signature, the latter
- // two expressed as a NameAndTypeEntry
- if (sym -> constant_pool_index == 0 || sym -> constant_pool_class != class_id) {
- TypeSymbol * owner = (TypeSymbol *) sym -> owner;
- sym -> constant_pool_index = BuildFieldref(
- RegisterClass(owner -> fully_qualified_name),
- BuildNameAndType(
- RegisterUtf8(sym -> ExternalIdentity()-> Utf8_literal),
- RegisterUtf8(sym-> Type() -> signature)));
- sym -> constant_pool_class = class_id;
- }
- return sym -> constant_pool_index;
- }
-
-
- void ByteCode::StoreSimple (int kind,AstExpression *p)
- {
- VariableSymbol * sym = (VariableSymbol *) p -> symbol;
- TypeSymbol * type = (TypeSymbol *) sym -> owner;
- TypeSymbol * expression_type = p-> Type();
- switch (kind) {
- case LHS_LOCAL:
- StoreLocalVariable(sym);
- break;
- case LHS_FIELD:
- case LHS_STATIC:
- {
- if (sym -> ACC_STATIC()) {
- PutOp(OP_PUTSTATIC);
- ChangeStack(this_control.IsDoubleWordType(expression_type) ? -2: -1);
- }
- else {
- PutOp(OP_ALOAD_0); // get address of "this"
- PutOp(OP_PUTFIELD);
- ChangeStack(this_control.IsDoubleWordType(expression_type) ? -3: -2);
- }
- PutU2(GenerateFieldReference(sym));
- break;
- default: chaos("StoreSimple bad kind");
- }
- }
- }
-
- // Methods to locate and build entries in constant pool.
- u2 ByteCode::BuildDouble(IEEEdouble d)
- {
- CONSTANT_Double_info *p = new CONSTANT_Double_info(CONSTANT_Double);
-
- p -> high_bytes = d.HighWord();
- p -> low_bytes = d.LowWord();
- constant_pool.Next() = p;
- constant_pool.Next() = 0; // extra slop for double-word entry
- return constant_pool.Length()-2;
- }
-
-
- u2 ByteCode::BuildFieldref(u2 cl_index, u2 nt_index)
- {
- CONSTANT_Fieldref_info *p = new CONSTANT_Fieldref_info(CONSTANT_Fieldref);
-
- p -> class_index = cl_index;
- p -> name_and_type_index = nt_index;
- constant_pool.Next() = p;
- return constant_pool.Length()-1;
- }
-
- u2 ByteCode::BuildFloat(IEEEfloat val)
- {
- CONSTANT_Float_info *p = new CONSTANT_Float_info(CONSTANT_Float);
- p -> bytes = val.Word();
- constant_pool.Next() = p;
- return constant_pool.Length()-1;
- }
-
- u2 ByteCode::BuildInteger(int val)
- {
- CONSTANT_Integer_info *p = new CONSTANT_Integer_info(CONSTANT_Integer);
- p -> bytes = ((val>>24 & 0xff) << 24) | ((val>>16 & 0xff) << 16)
- | ((val>>8 & 0xff) )<< 8 | (val&0xff);
- constant_pool.Next() = p;
- return constant_pool.Length()-1;
- }
-
- u2 ByteCode::BuildInterfaceMethodref(u2 cl_index, u2 nt_index)
- {
- CONSTANT_InterfaceMethodref_info *p = new CONSTANT_InterfaceMethodref_info(CONSTANT_InterfaceMethodref);
-
- p -> class_index = cl_index;
- p -> name_and_type_index = nt_index;
- constant_pool.Next() = p;
- return constant_pool.Length()-1;
- }
-
- u2 ByteCode::BuildLong(LongInt val)
- {
- CONSTANT_Long_info *p = new CONSTANT_Long_info(CONSTANT_Long);
-
- p -> high_bytes = val.HighWord();
- p -> low_bytes = val.LowWord();
- constant_pool.Next() = p;
- constant_pool.Next() = 0; // extra slop for double-word entry
- return constant_pool.Length()-2;
- }
- static char registered_methods_data[] = {
- //
- // This comment describes the strings below.
- //
- // "java/lang/Object","clone","()Ljava/lang/Object;", // Clone
- // "java/lang/Throwable","getMessage","()Ljava/lang/String;", // Clone_getMessage
- // "java/lang/InternalError","<init>","(Ljava/lang/String;)V", // Clone_init
- // "java/lang/StringBuffer","toString","()Ljava/lang/String;", // StringBuffer_toString
- // "java/lang/StringBuffer","<init>","()V", // StringBuffer_init
- // "java/lang/StringBuffer","append","([C)Ljava/lang/StringBuffer;", // StringBuffer_appendCharArray
- // "java/lang/StringBuffer","append","(C)Ljava/lang/StringBuffer;", // StringBuffer_appendChar
- // "java/lang/StringBuffer","append","(Z)Ljava/lang/StringBuffer;", // StringBuffer_appendBoolean
- // "java/lang/StringBuffer","append","(I)Ljava/lang/StringBuffer;", // StringBuffer_appendInt
- // "java/lang/StringBuffer","append","(J)Ljava/lang/StringBuffer;", // StringBuffer_appendLong
- // "java/lang/StringBuffer","append","(F)Ljava/lang/StringBuffer;", // StringBuffer_appendFloat
- // "java/lang/StringBuffer","append","(D)Ljava/lang/StringBuffer;", // StringBuffer_appendDouble
- // "java/lang/StringBuffer","append","(Ljava/lang/String;)Ljava/lang/StringBuffer;", // StringBuffer_appendString
- // "java/lang/StringBuffer","append","(Ljava/lang/Object;)Ljava/lang/StringBuffer;" // StringBuffer_appendObject
- //
- U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_O,U_b,U_j,U_e,U_c,U_t,U_NU,
- U_c,U_l,U_o,U_n,U_e,U_NU,
- U_LP,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_O,U_b,U_j,U_e,U_c,U_t,U_SC,U_NU, // Clone
-
- U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_T,U_h,U_r,U_o,U_w,U_a,U_b,U_l,U_e,U_NU,
- U_g,U_e,U_t,U_M,U_e,U_s,U_s,U_a,U_g,U_e,U_NU,
- U_LP,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_SC,U_NU, // Clone_getMessage
- U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_I,U_n,U_t,U_e,U_r,U_n,U_a,U_l,U_E,U_r,U_r,U_o,U_r,U_NU,
- U_LT,U_i,U_n,U_i,U_t,U_GT,U_NU,
- U_LP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_SC,U_RP,U_V,U_NU,
- // Clone_init
- U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
- U_t,U_o,U_S,U_t,U_r,U_i,U_n,U_g,U_NU,
- U_LP,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_SC,U_NU,
- // StringBuffer_toString
- U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
- U_LT,U_i,U_n,U_i,U_t,U_GT,U_NU,
- U_LP,U_RP,U_V,U_NU,
- // StringBuffer_init
- //"java/lang/StringBuffer",
- U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
- //"append",
- U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
-
- //"([C)Ljava/lang/StringBuffer;",
- U_LP,U_LB,U_C,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU,
- // StringBuffer_appendCharArray
- //"java/lang/StringBuffer",
- U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
- //"append",
- U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
- //"(C)Ljava/lang/StringBuffer;",
- U_LP,U_C,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU,
- // StringBuffer_appendChar
- //"java/lang/StringBuffer",
- U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
- //"append",
- U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
- //"(Z)Ljava/lang/StringBuffer;",
- U_LP,U_Z,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU,
- // StringBuffer_appendBoolean
- //"java/lang/StringBuffer",
- U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
- //"append",
- U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
- //"(I)Ljava/lang/StringBuffer;",
- U_LP,U_I,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU,
- // StringBuffer_appendInt
- //"java/lang/StringBuffer",
- U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
- //"append",
- U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
- //"(J)Ljava/lang/StringBuffer;",
- U_LP,U_J,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU,
- // StringBuffer_appendLong
- //"java/lang/StringBuffer",
- U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
- //"append",
- U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
- //"(F)Ljava/lang/StringBuffer;",
- U_LP,U_F,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU,
- // StringBuffer_appendFloat
- //"java/lang/StringBuffer",
- U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
- //"append",
- U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
- //"(D)Ljava/lang/StringBuffer;",
- U_LP,U_D,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU,
- // StringBuffer_appendDouble
- //"java/lang/StringBuffer",
- U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
- //"append",
- U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
- //"(Ljava/lang/String;)Ljava/lang/StringBuffer;",
- U_LP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_SC,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU,
- // StringBuffer_appendString
- //"java/lang/StringBuffer",
- U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_NU,
- //"append",
- U_a,U_p,U_p,U_e,U_n,U_d,U_NU,
- //"(Ljava/lang/Object;)Ljava/lang/StringBuffer;"
- U_LP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_O,U_b,U_j,U_e,U_c,U_t,U_SC,U_RP,U_L,U_j,U_a,U_v,U_a,U_SL,U_l,U_a,U_n,U_g,U_SL,U_S,U_t,U_r,U_i,U_n,U_g,U_B,U_u,U_f,U_f,U_e,U_r,U_SC,U_NU
- // StringBuffer_appendObject
- #ifdef DD
- #endif
- ,U_a // to mark end of last string
- };
-
- u2 ByteCode::RegisterMethod(int num)
- {
- // return index for use in method reference, building an entry if necessary.
- int pos = num * 3; // starting index of method descriptor
- // skip precdeing strings
- int i=0;
- char *p1, *p2, *p3, *p4;
- p1 = ®istered_methods_data[0];
- for (i=0;i<num;i++) {
- while (*p1++); // skip first string
- while (*p1++); // skip second string
- while (*p1++); // skip third string
- }
- p2=p1;
- while (*p2++); // move p2 to stard of second string
- p3=p2;
- while (*p3++); // move p3 to stard of third string
- p4=p3;
- while(*p4++); // move past end of third string
- if (registered_methods[num] == 0) {
- registered_methods[num] = BuildMethodref(
- RegisterClass(p1, p2-p1-1),
- BuildNameAndType(
- RegisterUtf8(p2, p3-p2-1),
- RegisterUtf8(p3, p4-p3-1)));
-
- }
- return registered_methods[num];
- }
- u2 ByteCode::BuildMethodref(u2 cl_index, u2 nt_index)
- {
- CONSTANT_Methodref_info *p = new CONSTANT_Methodref_info(CONSTANT_Methodref);
-
- p -> class_index = cl_index;
- p -> name_and_type_index = nt_index;
- constant_pool.Next() = p;
- return constant_pool.Length()-1;
- }
-
- u2 ByteCode::BuildNameAndType(u2 name, u2 type)
- {
- CONSTANT_NameAndType_info *p = new CONSTANT_NameAndType_info(CONSTANT_NameAndType);
-
- p -> name_index = name;
- p -> descriptor_index = type;
- constant_pool.Next() = p;
- return constant_pool.Length()-1;
- }
-
-
- u2 ByteCode::BuildString(u2 si)
- {
- CONSTANT_String_info *p = new CONSTANT_String_info(CONSTANT_String);
-
- p -> string_index = si;
- constant_pool.Next() = p;
- return constant_pool.Length()-1;
- }
-
- u2 ByteCode::BuildUtf8(char * s,int len)
- {
- CONSTANT_Utf8_info *p = new CONSTANT_Utf8_info(CONSTANT_Utf8);
- // build Utf8 from ASCII string (assume no embedded nulls), so just do straight copy
- p -> bytes = new char[len];
- // compute number of bytes in Utf8 form
- for (int i=0;i<len;i++) {
- p -> bytes[i] = s[i];
- }
- p -> length_ = len;
- constant_pool.Next() = p;
- return constant_pool.Length()-1;
- }
- u2 ByteCode::RegisterClass(Utf8LiteralValue * lit) {
- if (lit == (Utf8LiteralValue *) 0) chaos("null argument to RegisterClass");
- if (lit -> constant_pool_class != class_id) {
- // kill values assigned in prior class
- lit -> constant_pool_index_Class = 0;
- lit -> constant_pool_index_String = 0;
- lit -> constant_pool_index = 0;
- }
- if (lit -> constant_pool_index_Class == 0){
- CONSTANT_Class_info *ci = new CONSTANT_Class_info(CONSTANT_Class);
- ci -> name_index = (RegisterUtf8(lit));
- constant_pool.Next() = ci;
- lit -> constant_pool_index_Class = constant_pool.Length()-1;
- lit -> constant_pool_class = class_id;
- }
- return lit -> constant_pool_index_Class;
- }
-
- u2 ByteCode::RegisterClass(char * str, int len) {
- return RegisterClass(this_control.Utf8_pool.FindOrInsert(str,len));
- }
-
- u2 ByteCode::RegisterDouble(DoubleLiteralValue * lit) {
- if (lit == (DoubleLiteralValue *) 0) chaos("null argument to RegisterDouble");
- if (lit -> constant_pool_index == 0 || lit -> constant_pool_class != class_id){
- lit -> constant_pool_index = BuildDouble(lit -> value);
- lit -> constant_pool_class = class_id;
- }
- return lit -> constant_pool_index;
- }
-
- u2 ByteCode::RegisterInteger(IntLiteralValue * lit) {
- if (lit == (IntLiteralValue *) 0) chaos("null argument to RegisterInteger");
- if (lit -> constant_pool_index == 0 || lit -> constant_pool_class != class_id){
- lit -> constant_pool_index = BuildInteger(lit -> value);
- lit -> constant_pool_class = class_id;
- }
- return lit -> constant_pool_index;
- }
-
- u2 ByteCode::RegisterLong(LongLiteralValue * lit) {
- if (lit == (LongLiteralValue *) 0) chaos("null argument to RegisterLong");
- if (lit -> constant_pool_index == 0|| lit -> constant_pool_class != class_id){
- lit -> constant_pool_index = BuildLong(lit -> value);
- lit -> constant_pool_class = class_id;
- }
- return lit -> constant_pool_index;
- }
- u2 ByteCode::RegisterFloat(FloatLiteralValue * lit) {
- if (lit == (FloatLiteralValue *) 0) chaos("null argument to RegisterFloat");
- if (lit -> constant_pool_index == 0 || lit -> constant_pool_class != class_id){
- lit -> constant_pool_index = BuildFloat(lit -> value);
- lit -> constant_pool_class = class_id;
- }
- return lit -> constant_pool_index;
- }
-
-
- u2 ByteCode::RegisterString(Utf8LiteralValue * lit) {
- if (lit == (Utf8LiteralValue *) 0) chaos("null argument to RegisterString");
- if (lit -> constant_pool_class != class_id) {
- // kill values assigned in prior class
- lit -> constant_pool_index_Class = 0;
- lit -> constant_pool_index_String = 0;
- lit -> constant_pool_index = 0;
- }
- if (lit -> constant_pool_index_String == 0){
- lit -> constant_pool_index_String = BuildString(RegisterUtf8(lit));
- }
- return lit -> constant_pool_index_String;
- }
-
- u2 ByteCode::RegisterUtf8(Utf8LiteralValue * lit) {
- if (lit == (Utf8LiteralValue *) 0) chaos("null argument to RegisterUtf8");
- if (lit -> constant_pool_class != class_id) {
- // kill values assigned in prior class
- lit -> constant_pool_index_Class = 0;
- lit -> constant_pool_index_String = 0;
- lit -> constant_pool_index = 0;
- }
- if (lit -> constant_pool_index == 0){
- lit -> constant_pool_index = BuildUtf8(lit -> value,lit -> length);
- lit -> constant_pool_class = class_id;
- }
- return lit -> constant_pool_index;
- }
-
- u2 ByteCode::RegisterUtf8(char * str, int len) {
- return RegisterUtf8(this_control.Utf8_pool.FindOrInsert(str,len));
- }
-
-
-
- // Methods to write out the byte code
- Deprecated_attribute * ByteCode::CreateDeprecatedAttribute()
- {
-
- Deprecated_attribute * deprecated_attribute;
- u2 deprecated_attribute_name;
- u4 deprecated_attribute_length = 0;
- deprecated_attribute_name = RegisterUtf8(U8S_Deprecated, strlen(U8S_Deprecated));
- deprecated_attribute = new Deprecated_attribute(deprecated_attribute_name, deprecated_attribute_length);
- return deprecated_attribute;
- }
-
- Synthetic_attribute * ByteCode::CreateSyntheticAttribute()
- {
-
- Synthetic_attribute * synthetic_attribute;
- u2 synthetic_attribute_name;
- u4 synthetic_attribute_length = 0;
- synthetic_attribute_name = RegisterUtf8(U8S_Synthetic, strlen(U8S_Synthetic));
- synthetic_attribute = new Synthetic_attribute(synthetic_attribute_name, synthetic_attribute_length);
- return synthetic_attribute;
- }
-
- void ByteCode::FinishCode(TypeSymbol * type)
- {
- // finish off code by writing SourceFile attribute
- // and InnerClasses attribute (if appropriate)
- u4 sourcefile_attribute_length = 2;
- int file_name_start=0;
- int delim=-1; // location of last delimiter in file name
- TypeSymbol * class_type;
- int i;
- u2 name;
- char *file_name = this_semantic.lex_stream -> FileName();
- int file_name_length = this_semantic.lex_stream -> FileNameLength();
- for (i = file_name_length; i >= 0; i--)
- {
- if (file_name[i] == U_SLASH)
- {
- delim = i;
- break;
- }
- }
- // define Source Attribute
-
- if (delim != -1) {
- file_name_start = delim+1;
- file_name_length -= (delim + 1);
- }
- name = RegisterUtf8(U8S_Sourcefile, strlen(U8S_Sourcefile));
- SourceFile_attribute * sourcefile_attribute =
- new SourceFile_attribute(name, sourcefile_attribute_length);
- sourcefile_attribute -> sourcefile_index =
- BuildUtf8(file_name+file_name_start, file_name_length);
- attributes.Next() = sourcefile_attribute;
- if (type==(TypeSymbol *) 0) return; // return if interface type
- if (type -> IsLocal() || type -> IsNested() || type -> NumNestedTypes() > 0) {
-
- // here to generate InnerClasses attribute
- u4 inner_classes_attribute_length = 0;
- name = RegisterUtf8(U8S_InnerClasses, strlen(U8S_InnerClasses));
- inner_classes_attribute =
- new InnerClasses_attribute(name, inner_classes_attribute_length);
- inner_classes_attribute -> attribute_name_index = name;
- Tuple<TypeSymbol *> owners;
- // need to build chain from this type to its owner all the way to the containing type
- // and then write that out in reverse order (so containing type comes first),
- // and then write out an entry for each immediately contained type
- TypeSymbol * this_type = type;
- if (this_type != type -> outermost_type) {
- for (this_type = type;this_type != ((TypeSymbol *) 0) && this_type != type -> outermost_type;this_type = this_type -> ContainingType()) {
- owners.Next() = this_type;
- }
- }
-
- for (i = owners.Length();i > 0; i--) {
- SetInnerAttribute(owners[i - 1]);
- }
-
- for (i = 0; i < type -> NumNestedTypes(); i++) {
- SetInnerAttribute(type -> NestedType(i));
- }
-
- inner_classes_attribute -> attribute_length =
- inner_classes_attribute -> inner_classes.Length() * 8 + 2;
- attributes.Next() = inner_classes_attribute;
- }
- }
- void ByteCode::AddLocalVariableTableEntry(u2 start,u2 length,u2 name,u2 descriptor,u2 index)
- {
- // make entry in local variable table
- int li = local_variable_table_attribute -> local_variable_table.NextIndex();
- local_variable_table_attribute -> local_variable_table[li].start_pc = start;
- local_variable_table_attribute -> local_variable_table[li].length = length;
- local_variable_table_attribute -> local_variable_table[li].name_index = name;
- local_variable_table_attribute -> local_variable_table[li].descriptor_index = descriptor;
- local_variable_table_attribute -> local_variable_table[li].index = index;
- }
-
- void ByteCode::SetInnerAttribute(TypeSymbol * itype)
- {
- int i = inner_classes_attribute -> inner_classes.NextIndex();
- inner_classes_attribute -> inner_classes[i].inner_class_info_index = RegisterClass(itype -> fully_qualified_name);
- if (itype -> IsLocal()) {
- inner_classes_attribute -> inner_classes[i].outer_class_info_index = 0;
- }
- else {
- TypeSymbol * otype = itype -> ContainingType();
- inner_classes_attribute -> inner_classes[i].outer_class_info_index = RegisterClass(otype -> fully_qualified_name);
- }
- if (itype -> Anonymous()) {
- inner_classes_attribute -> inner_classes[i].inner_name_index = 0;
- }
- else {
- inner_classes_attribute -> inner_classes[i].inner_name_index = RegisterUtf8(itype -> name_symbol -> Utf8_literal);
- }
- AccessFlags flags;
- flags.access_flags = itype -> access_flags;
- inner_classes_attribute -> inner_classes[i].inner_class_access_flags = flags.access_flags;
- }
- // Methods to insert values into byte code
-
- void ByteCode::PutI1(i1 i)
- {
- code_attribute -> code.Next() = i&0xff;
- }
-
- void ByteCode::PutI2(i2 i)
- {
- code_attribute -> code.Next() = (i>>8) & 0xff;
- code_attribute -> code.Next() = i & 0xff;
- }
-
- void ByteCode::PutU1(u1 u)
- {
- code_attribute -> code.Next() = u & 0xff;
- }
-
- void ByteCode::PutU2(u2 u)
- {
- code_attribute -> code.Next() = (u>>8) & 0xff;
- code_attribute -> code.Next() = u & 0xff;
- }
-
- void ByteCode::PutU4(u4 u)
- {
- code_attribute -> code.Next() = (u>>24) & 0xff;
- code_attribute -> code.Next() = (u>>16) & 0xff;
- code_attribute -> code.Next() = (u>>8) & 0xff;
- code_attribute -> code.Next() = u & 0xff;
- }
-
- // stack_effect gives effect on stack of executing an opcode
-
- static int stack_effect[] =
- {
- 0, // OP_NOP
- 1, // OP_ACONST_NULL
- 1, // OP_ICONST_M1
- 1, // OP_ICONST_0
- 1, // OP_ICONST_1
- 1, // OP_ICONST_2
- 1, // OP_ICONST_3
- 1, // OP_ICONST_4
- 1, // OP_ICONST_5
- 2, // OP_LCONST_0
- 2, // OP_LCONST_1
- 1, // OP_FCONST_0
- 1, // OP_FCONST_1
- 1, // OP_FCONST_2
- 2, // OP_DCONST_0
- 2, // OP_DCONST_1
- 1, // OP_BIPUSH
- 1, // OP_SIPUSH
- 1, // OP_LDC
- 1, // OP_LDC_W
- 2, // OP_LDC2_W
- 1, // OP_ILOAD
- 2, // OP_LLOAD
- 1, // OP_FLOAD
- 2, // OP_DLOAD
- 1, // OP_ALOAD
- 1, // OP_ILOAD_0
- 1, // OP_ILOAD_1
- 1, // OP_ILOAD_2
- 1, // OP_ILOAD_3
- 2, // OP_LLOAD_0
- 2, // OP_LLOAD_1
- 2, // OP_LLOAD_2
- 2, // OP_LLOAD_3
- 1, // OP_FLOAD_0
- 1, // OP_FLOAD_1
- 1, // OP_FLOAD_2
- 1, // OP_FLOAD_3
- 2, // OP_DLOAD_0
- 2, // OP_DLOAD_1
- 2, // OP_DLOAD_2
- 2, // OP_DLOAD_3
- 1, // OP_ALOAD_0
- 1, // OP_ALOAD_1
- 1, // OP_ALOAD_2
- 1, // OP_ALOAD_3
- -1, // OP_IALOAD
- 0, // OP_LALOAD
- -1, // OP_FALOAD
- 0, // OP_DALOAD
- -1, // OP_AALOAD
- -1, // OP_BALOAD
- -1, // OP_CALOAD
- -1, // OP_SALOAD
- -1, // OP_ISTORE
- -2, // OP_LSTORE
- -1, // OP_FSTORE
- -2, // OP_DSTORE
- -1, // OP_ASTORE
- -1, // OP_ISTORE_0
- -1, // OP_ISTORE_1
- -1, // OP_ISTORE_2
- -1, // OP_ISTORE_3
- -2, // OP_LSTORE_0
- -2, // OP_LSTORE_1
- -2, // OP_LSTORE_2
- -2, // OP_LSTORE_3
- -1, // OP_FSTORE_0
- -1, // OP_FSTORE_1
- -1, // OP_FSTORE_2
- -1, // OP_FSTORE_3
- -2, // OP_DSTORE_0
- -2, // OP_DSTORE_1
- -2, // OP_DSTORE_2
- -2, // OP_DSTORE_3
- -1, // OP_ASTORE_0
- -1, // OP_ASTORE_1
- -1, // OP_ASTORE_2
- -1, // OP_ASTORE_3
- -3, // OP_IASTORE
- -4, // OP_LASTORE
- -3, // OP_FASTORE
- -4, // OP_DASTORE
- -3, // OP_AASTORE
- -3, // OP_BASTORE
- -3, // OP_CASTORE
- -3, // OP_SASTORE
- -1, // OP_POP
- -2, // OP_POP2
- 1, // OP_DUP
- 1, // OP_DUP_X1
- 1, // OP_DUP_X2
- 2, // OP_DUP2
- 2, // OP_DUP2_X1
- 2, // OP_DUP2_X2
- 0, // OP_SWAP
- -1, // OP_IADD
- -2, // OP_LADD
- -1, // OP_FADD
- -2, // OP_DADD
- -1, // OP_ISUB
- -2, // OP_LSUB
- -1, // OP_FSUB
- -2, // OP_DSUB
- -1, // OP_IMUL
- -2, // OP_LMUL
- -1, // OP_FMUL
- -2, // OP_DMUL
- -1, // OP_IDIV
- -2, // OP_LDIV
- -1, // OP_FDIV
- -2, // OP_DDIV
- -1, // OP_IREM
- -2, // OP_LREM
- -1, // OP_FREM
- -2, // OP_DREM
- 0, // OP_INEG
- 0, // OP_LNEG
- 0, // OP_FNEG
- 0, // OP_DNEG
- -1, // OP_ISHL
- -1, // OP_LSHL
- -1, // OP_ISHR
- -1, // OP_LSHR
- -1, // OP_IUSHR
- -1, // OP_LUSHR
- -1, // OP_IAND
- -2, // OP_LAND
- -1, // OP_IOR
- -2, // OP_LOR
- -1, // OP_IXOR
- -2, // OP_LXOR
- 0, // OP_IINC
- 1, // OP_I2L
- 0, // OP_I2F
- 1, // OP_I2D
- -1, // OP_L2I
- -1, // OP_L2F
- 0, // OP_L2D
- 0, // OP_F2I
- 1, // OP_F2L
- 1, // OP_F2D
- -1, // OP_D2I
- 0, // OP_D2L
- -1, // OP_D2F
- 0, // OP_I2B
- 0, // OP_I2C
- 0, // OP_I2S
- -3, // OP_LCMP
- -1, // OP_FCMPL
- -1, // OP_FCMPG
- -3, // OP_DCMPL
- -3, // OP_DCMPG
- -1, // OP_IFEQ
- -1, // OP_IFNE
- -1, // OP_IFLT
- -1, // OP_IFGE
- -1, // OP_IFGT
- -1, // OP_IFLE
- -2, // OP_IF_ICMPEQ
- -2, // OP_IF_ICMPNE
- -2, // OP_IF_ICMPLT
- -2, // OP_IF_ICMPGE
- -2, // OP_IF_ICMPGT
- -2, // OP_IF_ICMPLE
- -2, // OP_IF_ACMPEQ
- -2, // OP_IF_ACMPNE
- 0, // OP_GOTO
- 1, // OP_JSR
- 0, // OP_RET
- -1, // OP_TABLESWITCH
- -1, // OP_LOOKUPSWITCH
- -1, // OP_IRETURN
- -2, // OP_LRETURN
- -1, // OP_FRETURN
- -2, // OP_DRETURN
- -1, // OP_ARETURN
- 0, // OP_RETURN
- 0, // OP_GETSTATIC, caller must adjust if long or double
- 0, // OP_PUTSTATIC, caller must adjust if long or double
- 0, // OP_GETFIELD, caller must adjust if long or double
- 0, // OP_PUTFIELD, caller must adjust if long or double
- -1, // OP_INVOKEVIRTUAL, actually -1-args_length
- -1, // OP_INVOKENONVIRTUAL, actually -1-args_length
- 0, // OP_INVOKESTATIC, actually -args_length
- -1, // OP_INVOKEINTERFACE, actually -1 -args_length
- 0, // OP_XXXUNUSEDXXX
- 1, // OP_NEW
- 0, // OP_NEWARRAY
- 0, // OP_ANEWARRAY
- 0, // OP_ARRAYLENGTH
- 0, // OP_ATHROW
- 0, // OP_CHECKCAST
- 0, // OP_INSTANCEOF
- -1, // OP_MONITORENTER
- -1, // OP_MONITOREXIT
- 0, // OP_WIDE
- 0, // OP_MULTIANEWARRAY, actually dims-1
- -1, // OP_IFNULL
- -1, // OP_IFNONNULL
- 0, // OP_GOTO_W
- 1, // OP_JSR_W
- 0, // OP_SOFTWARE
- 0 // OP_HARDWARE
- };
-
- void ByteCode::PutNop(int optional)
- {
- // emit NOP. The NOP can be replaced by the next instruction if
- // optional is set; otherwise it must be kept.
- PutOp(OP_NOP);
- // this optimization is causing more trouble than it's worth.
- // latest problem (27 jan 97) was reported by Derek, in that
- // nop just before label definition, resulted in operation generated
- // after label def. being moved before the def! Since it's such a sin
- // to generate junk code, disable the "nop" optimization.
- // if (optional) last_op_nop = 1;
- }
-
- void ByteCode::PutOp(unsigned char opc)
- {
- #ifdef TEST
- int len = code_attribute -> code.Length(); // show current position
- if (this_control.option.debug_trap_op >0 && code_attribute -> code.Length() == this_control.option.debug_trap_op) {
- op_trap();
- }
- // debug trick - force branch on opcode to see what opcode we are compiling
- switch (opc) {
- case OP_NOP: break;
- case OP_ACONST_NULL: break;
- case OP_ICONST_M1: break;
- case OP_ICONST_0: break;
- case OP_ICONST_1: break;
- case OP_ICONST_2: break;
- case OP_ICONST_3: break;
- case OP_ICONST_4: break;
- case OP_ICONST_5: break;
- case OP_LCONST_0: break;
- case OP_LCONST_1: break;
- case OP_FCONST_0: break;
- case OP_FCONST_1: break;
- case OP_FCONST_2: break;
- case OP_DCONST_0: break;
- case OP_DCONST_1: break;
- case OP_BIPUSH: break;
- case OP_SIPUSH: break;
- case OP_LDC: break;
- case OP_LDC_W: break;
- case OP_LDC2_W: break;
- case OP_ILOAD: break;
- case OP_LLOAD: break;
- case OP_FLOAD: break;
- case OP_DLOAD: break;
- case OP_ALOAD: break;
- case OP_ILOAD_0: break;
- case OP_ILOAD_1: break;
- case OP_ILOAD_2: break;
- case OP_ILOAD_3: break;
- case OP_LLOAD_0: break;
- case OP_LLOAD_1: break;
- case OP_LLOAD_2: break;
- case OP_LLOAD_3: break;
- case OP_FLOAD_0: break;
- case OP_FLOAD_1: break;
- case OP_FLOAD_2: break;
- case OP_FLOAD_3: break;
- case OP_DLOAD_0: break;
- case OP_DLOAD_1: break;
- case OP_DLOAD_2: break;
- case OP_DLOAD_3: break;
- case OP_ALOAD_0: break;
- case OP_ALOAD_1: break;
- case OP_ALOAD_2: break;
- case OP_ALOAD_3: break;
- case OP_IALOAD: break;
- case OP_LALOAD: break;
- case OP_FALOAD: break;
- case OP_DALOAD: break;
- case OP_AALOAD: break;
- case OP_BALOAD: break;
- case OP_CALOAD: break;
- case OP_SALOAD: break;
- case OP_ISTORE: break;
- case OP_LSTORE: break;
- case OP_FSTORE: break;
- case OP_DSTORE: break;
- case OP_ASTORE: break;
- case OP_ISTORE_0: break;
- case OP_ISTORE_1: break;
- case OP_ISTORE_2: break;
- case OP_ISTORE_3: break;
- case OP_LSTORE_0: break;
- case OP_LSTORE_1: break;
- case OP_LSTORE_2: break;
- case OP_LSTORE_3: break;
- case OP_FSTORE_0: break;
- case OP_FSTORE_1: break;
- case OP_FSTORE_2: break;
- case OP_FSTORE_3: break;
- case OP_DSTORE_0: break;
- case OP_DSTORE_1: break;
- case OP_DSTORE_2: break;
- case OP_DSTORE_3: break;
- case OP_ASTORE_0: break;
- case OP_ASTORE_1: break;
- case OP_ASTORE_2: break;
- case OP_ASTORE_3: break;
- case OP_IASTORE: break;
- case OP_LASTORE: break;
- case OP_FASTORE: break;
- case OP_DASTORE: break;
- case OP_AASTORE: break;
- case OP_BASTORE: break;
- case OP_CASTORE: break;
- case OP_SASTORE: break;
- case OP_POP: break;
- case OP_POP2: break;
- case OP_DUP: break;
- case OP_DUP_X1: break;
- case OP_DUP_X2: break;
- case OP_DUP2: break;
- case OP_DUP2_X1: break;
- case OP_DUP2_X2: break;
- case OP_SWAP: break;
- case OP_IADD: break;
- case OP_LADD: break;
- case OP_FADD: break;
- case OP_DADD: break;
- case OP_ISUB: break;
- case OP_LSUB: break;
- case OP_FSUB: break;
- case OP_DSUB: break;
- case OP_IMUL: break;
- case OP_LMUL: break;
- case OP_FMUL: break;
- case OP_DMUL: break;
- case OP_IDIV: break;
- case OP_LDIV: break;
- case OP_FDIV: break;
- case OP_DDIV: break;
- case OP_IREM: break;
- case OP_LREM: break;
- case OP_FREM: break;
- case OP_DREM: break;
- case OP_INEG: break;
- case OP_LNEG: break;
- case OP_FNEG: break;
- case OP_DNEG: break;
- case OP_ISHL: break;
- case OP_LSHL: break;
- case OP_ISHR: break;
- case OP_LSHR: break;
- case OP_IUSHR: break;
- case OP_LUSHR: break;
- case OP_IAND: break;
- case OP_LAND: break;
- case OP_IOR: break;
- case OP_LOR: break;
- case OP_IXOR: break;
- case OP_LXOR: break;
- case OP_IINC: break;
- case OP_I2L: break;
- case OP_I2F: break;
- case OP_I2D: break;
- case OP_L2I: break;
- case OP_L2F: break;
- case OP_L2D: break;
- case OP_F2I: break;
- case OP_F2L: break;
- case OP_F2D: break;
- case OP_D2I: break;
- case OP_D2L: break;
- case OP_D2F: break;
- case OP_I2B: break;
- case OP_I2C: break;
- case OP_I2S: break;
- case OP_LCMP: break;
- case OP_FCMPL: break;
- case OP_FCMPG: break;
- case OP_DCMPL: break;
- case OP_DCMPG: break;
- case OP_IFEQ: break;
- case OP_IFNE: break;
- case OP_IFLT: break;
- case OP_IFGE: break;
- case OP_IFGT: break;
- case OP_IFLE: break;
- case OP_IF_ICMPEQ: break;
- case OP_IF_ICMPNE: break;
- case OP_IF_ICMPLT: break;
- case OP_IF_ICMPGE: break;
- case OP_IF_ICMPGT: break;
- case OP_IF_ICMPLE: break;
- case OP_IF_ACMPEQ: break;
- case OP_IF_ACMPNE: break;
- case OP_GOTO: break;
- case OP_JSR: break;
- case OP_RET: break;
- case OP_TABLESWITCH: break;
- case OP_LOOKUPSWITCH: break;
- case OP_IRETURN: break;
- case OP_LRETURN: break;
- case OP_FRETURN: break;
- case OP_DRETURN: break;
- case OP_ARETURN: break;
- case OP_RETURN: break;
- case OP_GETSTATIC: break;
- case OP_PUTSTATIC: break;
- case OP_GETFIELD: break;
- case OP_PUTFIELD: break;
- case OP_INVOKEVIRTUAL: break;
- case OP_INVOKENONVIRTUAL: break;
- case OP_INVOKESTATIC: break;
- case OP_INVOKEINTERFACE: break;
- case OP_XXXUNUSEDXXX: break;
- case OP_NEW: break;
- case OP_NEWARRAY: break;
- case OP_ANEWARRAY: break;
- case OP_ARRAYLENGTH: break;
- case OP_ATHROW: break;
- case OP_CHECKCAST: break;
- case OP_INSTANCEOF: break;
- case OP_MONITORENTER: break;
- case OP_MONITOREXIT: break;
- case OP_WIDE: break;
- case OP_MULTIANEWARRAY: break;
- case OP_IFNULL: break;
- case OP_IFNONNULL: break;
- case OP_GOTO_W: break;
- case OP_JSR_W: break;
- case OP_SOFTWARE: break;
- case OP_HARDWARE: break;
- }
- #endif
- last_op_pc = code_attribute -> code.Length(); // save pc at start of operation
- #ifdef NOP_OPT
- // this optimization doesn't work - disable for now
- // if (last_op_nop) {
- // last_op_nop = 0;
- // code_attribute -> code[last_op_pc - 1] = opc;
- // }
- // else {
- // code_attribute -> code.Next() = opc;
- // }
- #else
- code_attribute -> code.Next() = opc;
- #endif
- ChangeStack(stack_effect[opc]);
- }
- void ByteCode::ChangeStack(int i)
- {
- stack_depth += i;
- if (stack_depth < 0) stack_depth = 0;
- if (i>0 && stack_depth > code_attribute -> max_stack) {
- code_attribute -> max_stack = stack_depth;
- }
- #ifdef TRACE_STACK_CHANGE
- cout << "stack change: pc " << last_op_pc << " change " << i <<
- " stack_depth " << stack_depth << " max_stack: "<< code_attribute -> max_stack << "\n";
- #endif
- }
-
- #ifdef TEST
- void ByteCode::PrintCode()
- {
- int i;
- cout << "magic " << hex << magic << dec
- << " major_version " << major_version
- << " minor_version " << minor_version << "\n";
- AccessFlags::Print();
- cout << "\n";
- cout << " this_class " << this_class << " super_class " << super_class <<"\n";
- cout << " constant_pool: " << constant_pool.Length() << "\n";
- for (i=1;i<constant_pool.Length();i++) {
- cout << " " << i << " ";
- constant_pool[i] -> print(constant_pool);
- if (constant_pool[i] -> tag == CONSTANT_Long ||
- constant_pool[i] -> tag == CONSTANT_Double) {
- i++;; // skip the next entry for eight-byte constants
- }
- }
- cout << " interfaces " << interfaces.Length() <<": ";
- for (i=0;i<interfaces.Length();i++) cout << " " << (int) interfaces[i];
- cout <<"\n";
- for (i=0;i<fields.Length();i++) {
- cout << "field " << i << "\n";
- fields[i].print(constant_pool);
- }
- cout << " methods length " << methods.Length() << "\n";
- for (i=0;i<methods.Length();i++) {
- cout << "method " << i << "\n";
- methods[i].print(constant_pool);
- }
- for (i=0;i<attributes.Length();i++) {
- cout << "attribute " << i << "\n";
- attributes[i] -> print(constant_pool);
- }
- cout << "\n";
- }
- #endif
-